c - 为什么 GCC 会优化重要的赋值,使其变成不同的程序行为?
问题描述
因此,我正在为我的控制台解释器制作一个 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
and -fdata-sections
,也未检测到分配)。
但是,当我更改涉及 around tvar
OR around的代码时_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
,既不直接也不通过指针访问变量,之后由于它是本地的,所以生命周期结束。而且您只能在其生命周期内访问。因此编译器完全有权优化分配,因为它不会对正确的程序产生任何影响。retpoint
tvar = _wtoi(expr);
eval
tvar
tvar
如果它确实改变了你的程序的行为,那么你可能在某处有未定义的行为。也许您在返回retpoint
后取消引用指针。eval
那绝对是UB。一般来说,设置一个全局指针指向一个局部变量,并在函数返回后将其保留在那里,是非常可疑的。
推荐阅读
- java - 添加 MongoDB 策略提供程序扩展后的 RuntimeException
- javascript - 在angularjs中单击时将div向左移动
- c# - Linq 从嵌套列表中查找所有具有 id 的元素
- database - 简单的用户权限数据库结构
- google-cloud-platform - 在谷歌云上的 slurm 部署中更改 ControlPort
- angular - 通过 @ContentChildren 或 @ContentChild 传递的渲染组件
- react-native - 权限 Android for iOS in React Native
- json - 有没有办法在 JSON 响应中返回 null?
- excel - 在excel Vba中引用字符串时如何忽略特殊字符
- json - 在 Xcode 中按 JSON 显示数据库中的数据