[英]Why did GCC optimizes important assignment, making it into a different program behavior?
所以,我正在為我的控制台解釋器制作一個 C 程序來檢測它是哪種類型,然后將它返回到typeret
並將指針存儲到 void 指針retpoint
。 現在,我要問的不是代碼中的內容,而是為什么GCC 在我的函數eval
優化此分配。 我想知道為什么 GCC 優化了一些真正重要的東西。
int eval(wchar_t *expr) {
// ....
if (expr[0] == L'\'' && expr[csize - 1] == L'\'') { // <-- Ignore this.
expr[csize - 1] = 0;
typeret = 0;
retpoint = (expr + 1);
} else if (strin(L".", expr)) { // <-- Ignore this.
typeret = 2;
} else {
typeret = 1;
tvar = _wtoi(expr); // <-- Here is the problem.
retpoint = &tvar;
}
return 0;
}
當我使用 GCC 命令編譯代碼時, gcc -Wsomewarning -o cim.exe cim.c -Os -s -ffunction-sections -fdata-sections -O3
,未檢測到分配(即使沒有-ffunction-sections
和-fdata-sections
,也未檢測到分配)。
但是,當我更改涉及tvar
或_wtoi
周圍的代碼時,分配不會被忽略。 這是不忽略賦值的示例代碼。
int eval(wchar_t *expr) {
int
tvar; // If I set tvar to N, then the assignment is still ignored (making tvar = N).
// ....
if (expr[0] == L'\'' && expr[csize - 1] == L'\'') { // <-- Ignore this.
expr[csize - 1] = 0;
typeret = 0;
retpoint = (expr + 1);
} else if (strin(L".", expr)) { // <-- Ignore this.
typeret = 2;
} else {
typeret = 1;
tvar = _wtoi(expr); // <-- Here is the problem.
wprintf(L"%d", tvar); // or wprintf(L"%d", _wtoi(expr);
retpoint = &tvar;
}
return 0;
}
現在,當然,如果我使用gcc -o cim.exe cim.c
(沒有優化),第一個代碼工作正常; 然而,尺寸是優化尺寸的四倍。
筆記
我確信這個程序中沒有未定義的行為,並且我確信我已經正確地提供了數據。
typeret
和retpoint
是全局數據,而tvar
是局部變量。
編輯
我忘了提到我在 Windows 10 中使用了 GCC 版本 (tdm64-1) 4.9.2。
提前致謝。
在您的第一個示例中,變量tvar
在賦值tvar = _wtoi(expr);
之間既不直接也不通過指針retpoint
訪問tvar = _wtoi(expr);
當函數eval
返回時,之后tvar
的生命周期結束,因為它是本地的。 並且您只能在其生命周期內訪問tvar
。 因此編譯器完全有權優化分配,因為它不會對正確的程序產生任何影響。
如果它確實改變了你的程序的行為,那么你可能在某處有未定義的行為。 也許您在eval
返回后取消引用指針retpoint
。 那絕對是UB。 通常,將全局指針設置為指向局部變量,並在函數返回后將其留在那里,是非常可疑的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.