|
From: Nicholas N. <nj...@cs...> - 2006-06-05 21:57:27
|
On Mon, 5 Jun 2006, Bob Rossi wrote: > OK, if we include > #define _GNU_SOURCE /* ptsname_r() under Linux */ > #include <sys/types.h> > we get the prototype > extern char *ptsname (int __fd) __attribute__ ((__nothrow__)); > in the translation unit. > > If we include > #include <sys/types.h> > #define _GNU_SOURCE /* ptsname_r() under Linux */ > we do not get the prototype in the translation unit. > > Then, we do this, > char *name; > if (!(name = ptsname(*masterfd))) > > In the case where the prototype is defined, it works fine and there > is no crash. In the case where there is no prototype, we get this > error. > ../../../../cgdb/various/util/src/pseudo.c:304: warning: assignment > makes pointer from integer without a cast > > That's because it thinks ptsname returns an int, and assigns it to a > char*. This works when the sizeof(char*) == sizeof(int). However on this > 64 amd machine, sizeof (char*)=8 sizeof (int)=4. This gives us the > crash. > > Now, I'm wondering why valgrind reports no error on this circumstance. > Would this be an improvement to memcheck? It took us quite some time to > figure out the problem. Here's my guess as to what happened. The lower 4 bytes of the return register (%rax, I think) got set to the return value. The upper 4 bytes got left as whatever they were before; but importantly, those 4 bytes were defined (ie. initialised). So the whole register is seen by Memcheck as defined, because it is. You then used that value as a pointer, which was bogus, but under Memcheck you got lucky/unlucky and the access through that pointer hit addressable memory. Or possibly(?) Valgrind changes the way the values go through the registers somewhat, and you luckily/unluckily ended up with the correct value. The problem is that Memcheck does all its analysis at the byte-level. But your problem here (assuming I've diagnosed it correctly) is that you erroneously combined two 4-byte values into an 8-byte value which you then used. As for whether Memcheck or another tool could detect this... it seems like it would be hard, because multi-byte values get constructed from single-byte or fewer-byte values all the time, and I can't think how to distinguish the erroneous ones from the legitimate ones. So it's something that Memcheck can't detect. But the compiler can :) Nick |