簡體   English   中英

VC ++ 6.0中的調試與發布行為之謎

[英]Debug vs Release behavior mystery in VC++ 6.0

對於下面的程序,我會得到不同的結果,具體取決於我是在Windows 7的VC ++ 6.0中以調試模式還是發布模式運行它。調試和發布行為的差異幾乎總是表示處理指針和循環的錯誤,但我無法發現錯誤。

在調試模式下,我得到了我期待的結果:

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

在發布模式下, 除了 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;
}

(更正先前注釋的更正):VC6 ++ SP6中的類似結果,但我根本沒有“正面”輸出。 我要去看看。 我們會看看能不能找到任何東西。 沒有承諾(Euro Micelli)

我已經復制了相同的結果(發布時沒有任何結果)@EuroMicelli發現。 但是,如果將RecordCountNew聲明為volatile,則輸出存在:

volatile int RecordCountNew = 0;

對於您的信息,volatile是一個關鍵字,它告訴編譯器可以在隨機時間(例如在CPU中斷期間)從外部修改變量,並防止編譯器積極優化其周圍的代碼。

tldrMSVC6錯誤地優化了RecordCountNew

PS:將RecordCountNew聲明為short而不是int使打印輸出重新出現。 你永遠不知道20年前編譯器的大腦里發生了什么。

PPS:因為我被要求解釋這個bug,這里是正確輸出的反匯編版本:

在此輸入圖像描述

edi寄存器存儲RecordCountNew值, test指令命令跳轉到printf 但是,這是OP的編譯版本:

在此輸入圖像描述

test條件是在基指針寄存器ebp ,它與RecordCountNew無關。 根據ebp的值,程序每次輸出行,或從不輸出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM