I have come across a very odd problem in C that I have never encountered before. I have narrowed it down to the following very simple snippet.
The variables are global and of type:
int cpd;
int nPart;
And here is the relevant code snippet which I gradually stripped down to the very minimum needed to produce the issue:
printf("\ncpd1: %d\n",cpd);
int p;
for(p=1;p<=nPart;p++)
{
printf("\ncpd2: %d\n",cpd); exit(0);
}
…The output I get is this:
cpd1: 17
cpd2: 0
How on earth is this possible?!
cpd has NOT been reassigned, NO functions have been called… yet it changed?
HOW?!?!
This has been driving me slowly insane for quite some time now…
… so any ideas?
thanks for your time,
Ben.
EDIT: and when I remove -02 from the makefile arguments to gcc, BOTH the print statements tell me that cpd = 0!
EDIT: Okay, I just found that a variable that is declared globally once, initialised as 4.0, and then never modified is now apparently 1.51086e-311 … Something is very wrong somewhere…
EDIT: SOLVED!: I had an array of size 1000 that needed to be over 4000, and trying to write to this was corrupting the memory around it. Thing is, this array is NOT accessed anywhere near those print statements, it is accessed in the same function however, much earlier on (large function!). The weird discrepancy between print statements must be some weird artifact of using -O2, as without -O2, both prints of cpd print the corrupted version. Thank you everyone, I wouldnt have worked this out without your help!
Stack frame corruption due to buffer overflow is the usual explanation for this. Here’s an example:
Output:
The “msg” string buffer is too short by one character, the string terminator overwrites the value of “cpd”.
The best way to find the cause is to use the data breakpoint feature of the debugger. Set a regular breakpoint on the function entry point. Then find the address of the “cpd” variable and a set a byte-size data breakpoint on it. The debugger will stop as soon as the cpd value changes.
Beware that this won’t necessarily work in optimized code, the “cpd” value might be stored in a register. Which is another possible explanation why its value is different in separate statements.