Debug vs Release Behavior in VC ++ 6.0
In the program below, I get different results depending on whether I run it in Debug or Release mode in VC ++ 6.0 on Windows 7. Differences in Debug and Release behavior almost always indicate errors in handling pointers and loops, but I I cannot indicate an error.
In debug mode, I get the expected results:
Entered loop with i == 0, RecordCountNew == 0
RecordCountNew = 1 is positive.
Entered loop with i == 1, RecordCountNew == 1
Adding record with i == 1, RecordCountNew == 1
Added record with i == 1, RecordCountNew == 2
RecordCountNew = 3 is positive.
Entered loop with i == 2, RecordCountNew == 3
RecordCountNew = 4 is positive.
Finished loop with i == 3, RecordCountNew == 4
In Release mode, I get the same results except for the statement that RecordCountNew is positive:
Entered loop with i == 0, RecordCountNew == 0
RecordCountNew = 1 is positive.
Entered loop with i == 1, RecordCountNew == 1
Adding record with i == 1, RecordCountNew == 1
Added record with i == 1, RecordCountNew == 2
RecordCountNew = 3 is positive.
Entered loop with i == 2, RecordCountNew == 3
Finished loop with i == 3, RecordCountNew == 4
Can anyone replicate this on their machine, or better yet, explain it?
#include <stdio.h>
#include <algorithm>
using namespace std;
struct record {
int ID;
};
int RecordLimit;
record* Records = NULL;
record** RecordIndex = NULL;
record** RecordIndexNew = NULL;
int main(int argc, char* argv[]) {
RecordLimit = 10;
Records = new (nothrow) record[RecordLimit];
RecordIndex = new (nothrow) record*[RecordLimit];
RecordIndexNew = new (nothrow) record*[RecordLimit];
int i;
for (i = 0; i < RecordLimit; i++) {
RecordIndex[i] = NULL;
RecordIndexNew[i] = NULL;
}
int RecordCount = 0;
for (i = 0; i < 3; i++) {
Records[i].ID = i;
RecordCount++;
}
int RecordCountNew = 0;
for (i = 0; i < RecordCount; i++) {
printf("Entered loop with i == %d, RecordCountNew == %d\n", i, RecordCountNew);
RecordIndexNew[RecordCountNew] = RecordIndex[i];
bool AddNewRecord = (i == 1);
if (AddNewRecord) {
printf("Adding record with i == %d, RecordCountNew == %d\n", i, RecordCountNew);
Records[RecordCount + (RecordCountNew - i)].ID = RecordCount + (RecordCountNew - i);
RecordIndexNew[RecordCountNew + 1] = RecordIndexNew[RecordCountNew];
RecordIndexNew[RecordCountNew] = &Records[RecordCount + (RecordCountNew - i)];
RecordCountNew++;
printf("Added record with i == %d, RecordCountNew == %d\n", i, RecordCountNew);
}
RecordCountNew++;
if (RecordCountNew > 0) printf("RecordCountNew == %d is positive.\n", RecordCountNew);
}
printf("Finished loop with i == %d, RecordCountNew == %d\n", i, RecordCountNew);
delete[] Records;
delete[] RecordIndex;
delete[] RecordIndexNew;
return 0;
}
source to share
(Correction replaces previous comment): Similar results in VC6 ++ SP6, but I don't get any positive results at all. I'll see. Let's see if I can find anything. No promises (Euro Micelli)
I replicated the same results (didn't pop up at all on Release) found by @EuroMicelli. However, if you declare RecordCountNew
as volatile, the outputs are present:
volatile int RecordCountNew = 0;
For your information, volatile is a keyword that tells the compiler that a variable can be changed externally at an arbitrary time (such as when the processor is interrupted) and prevents the compiler from aggressively optimizing the code around it.
TL; DR : MSVC6
Incorrectly optimized RecordCountNew
.
PS: declaring RecordCountNew
like short
instead int
will cause the print results to be re-displayed. You never know what's going on in the brain of a 20 year old compiler.
PPS: Since I am asked to explain the error, here is a parsed version of the correct output:
register will edi
store the value RecordCountNew
and command of the command test
to jump to printf
. However, here's the compiled version of the OP:
The condition test
is executed in the base pointer register ebp
, which has nothing to do with RecordCountNew
. Depending on the value, the ebp
program outputs the string every time or never.
source to share