对于下面的程序,根据我在 Windows 7 上的 VC++ 6.0 中以 Debug模式还是 Release模式运行它,我得到不同的结果。调试和发布行为的差异几乎总是表明处理指针和循环时存在错误,但我无法发现错误.

在 Debug模式下,我得到了预期的结果:

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

在 Release模式下,我得到了相同的结果, 除了 对于 RecordCountNew 为正的断言:
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

任何人都可以在他们的机器上复制这个,或者更好的是,解释一下?
#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;
}

最佳答案



我已经复制了相同的结果(发布时根本没有输出)@EuroMicelli 发现。但是,如果您将 RecordCountNew 声明为 volatile,则存在输出:

volatile int RecordCountNew = 0;

为了您的信息, volatile 是一个关键字,它告诉编译器可以在随机时间(例如在 CPU 中断期间)从外部修改变量,并防止编译器积极优化它周围的代码。

tldr :MSVC6 错误地优化了 RecordCountNew

PS:将 RecordCountNew 声明为 short 而不是 int 会使打印输出重新出现。你永远不知道一个 20 岁的编译器的大脑中发生了什么。

PPS:因为我被要求解释错误,这里是正确输出的反汇编版本:
edi 寄存器存储 RecordCountNew 值,test 指令命令跳转到 printf 。但是,这是 OP 的编译版本:
test 条件在基指针寄存器 ebp 上完成,与 RecordCountNew 无关。根据 ebp 的值,程序每次都输出该行,或者从不输出。

关于c++ - VC++ 6.0 中的调试与发布行为之谜,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31150747/

10-11 20:57