It should be fairly easy to use a debugger to see what is happening.
I will detail how to do this using gdb on linux. But the same principles applies also when using other debuggers.
1. Assuming that the source code is in a file called test.c, compile the source code on O0 and using the -g flag (to generate debug information).
In terminal run:
gcc -g -O0 test.c -o test -> this produces an executable called test
2. Double check that the issue reproduces:
In terminal run:
an inspect the output
3. Assuming that the issue reproduces, start the gdb debugger by running in terminal:
gdb -tui ./test -> is easier to use the tui mode
4. Set a breakpoint at this line:
listPtr->next = &newItem;
Run this from the gdb console:
(gdb) break test.c:14 --> 14 is the line number of the source line above.
3. Than run the program.
The program execution will stop after hitting the breakpoint.
Double check, in the source view, that you are at line 14.
4. Find out the address of the newItem local variable
(gdb) print &newItem
gdb will reply with something like this:
$1 = (struct listItem *) 0xbffff518
In my case, the address is 0xbffff518. In your case most likely will be a different address.
5. Now comes the interesting part.
Set a write watchpoint at the address found out at step 4.
(gdb) watch *(struct listItem *) 0xbffff518 --> update this for your address.
gdb will reply with something like this
Hardware watchpoint 2: *(struct listItem *) 0xbffff518
signaling that the watchpoint was set.
6. Continue the execution of the program
If the program will write to the address where you set the watchpoint, the execution will stop after the write access. This way you can find out exactly who is writing at that address.
gdb will reply when stopping with the current value of the EIP register (of course, an address).
In the source code you will also see which source code corresponds to that address.
You can double check that the returned address matches the EIP register content:
(gdb) info registers eip
So, all you have to do is to inspect the code just, knowing that you have stopped just after the content of the address (where the watchpoint was set) was written.
You can switch to disassembly in gdb and inspect the dissasembly:
(gdb) layout asm
If you want to disassemble the test executable outside gdb, you can use objdump:
objdump -d ./test
Edited by gonerogue, 18 March 2014 - 09:21 AM.