There is something terribly wrong with either gdb, gcc or both, and I don't know what. I've created开发者_如何学运维 a POC to reproduce it on gcc (GCC) 4.6.1 20110819 (prerelease)
and GNU gdb (GDB) 7.3.50.20110908-cvs
- yes, this is the CVS version, because I was running into this issue http://sourceware.org/bugzilla/show_bug.cgi?id=12435, however I've also tested with GNU gdb (GDB) 7.3.1
and it behaves the same.
Now to the POC: https://gist.github.com/1211017 the problem can be observed on line 33
In my opinion, *c->foos[i]
should evaluate to the address of the i-th foo, as displayed by line 21. But the executable crashes, as you can see in the output.
Does anyone know what is wrong? An explanation at either the ASM level or GCC internals would be welcome.
Addendum:
- The data structures are not allowed to change - they don't belong to my code, I have to interoperate with them.
- The code
*c->foos[i]
used to work with older versions of gcc. dump_container
must have as parameter acontainer*
- this function doesn't belong to my code either
Also worth mentioning: *c->foos[i]
used to work.
Running your code through the ever helpful valgrind says:
==16066== Use of uninitialised value of size 8 ==16066== at 0x40061B: dump_container (bug.c:33) ==16066== by 0x400726: main (bug.c:49) ==16066== ==16066== Invalid read of size 4 ==16066== at 0x400620: dump_container (stdio2.h:105) ==16066== by 0x400726: main (bug.c:49) ==16066== Address 0x89485ed18949ed39 is not stack'd, malloc'd or (recently) free'd ==16066== ==16066== ==16066== Process terminating with default action of signal 11 (SIGSEGV) ==16066== General Protection Fault ==16066== at 0x400620: dump_container (stdio2.h:105) ==16066== by 0x400726: main (bug.c:49) ==16066==
My guess is that you'll find the bug in your own code rather than the compiler or debugger.
EDIT Or since you want me to spell it out for you, change line 33 to
printf("foo[%d]=%d at %p\n", i, (*c->foos)[i]->i, (void*) (*c->foos)[i]);
I don't understand how *c->foos[i] would have ever worked, c->foos
gives a pointer to an array (a pointer to a bloc of pointers) (of pointers), according to line 43, when doing c->foos[i]
you're not accessing to an element of the array. (*c->foos)[i]
should work...
Take a look at the C Operator Precedence Table.
In my opinion, *c->foos[i] should evaluate to the address of the i-th foo, as displayed by line 21.
No. If that is what you mean, you should use &c->foos[i]
. Your version dereferences the i-th foo, what easily can lead to
But the executable crashes, as you can see in the output.
.
精彩评论