寻求含const_cast的未定义行为示例:GCC优化前后输出不同
优化对含未定义行为程序的影响示例
一、修改你原程序的可行变体
你的原程序中,编译器可能因为constant()是无副作用的纯函数,即使在-O0下也做了常量传播,导致优化前后输出一致。可以调整代码,让编译器无法在-O0时确定p的常量值,但优化时能通过未定义行为假设做常量折叠:
拆分编译单元实现
- 创建
blind.cpp文件:
void blind(int const* p) { ++*const_cast<int*>(p); }
- 主程序
main.cpp:
#include <iostream> // 声明blind,不定义在本单元,避免编译器内联优化 extern void blind(int const*); // 给constant函数添加微小副作用,阻止-O0下的常量传播 int constant() { static int cnt = 0; return cnt++; } int main() { int const p = constant(); blind(&p); std::cout << p << std::endl; return 0; }
编译运行结果
- 未优化编译:
g++ -O0 main.cpp blind.cpp -o test,运行输出1(未优化时直接读取内存中被修改后的值) - 开启-O3优化:
g++ -O3 main.cpp blind.cpp -o test_opt,运行输出0(编译器认为const变量p的值不会被修改,直接用constant()返回的初始值做常量输出)
二、经典有符号整数溢出示例(优化前后输出不同且不崩溃)
有符号整数溢出属于C++未定义行为,编译器会基于“溢出不会发生”的假设做优化,导致优化前后行为差异:
#include <iostream> int check_overflow(int x) { if (x > 0) { x += 1000000000; // 当x足够大时,此处触发有符号整数溢出 } // 编译器优化时会假设x>0时x+1e9仍>0,直接返回1 return x > 0 ? 1 : 0; } int main() { // 假设int为32位,最大值为2147483647,2000000000+1000000000=3000000000超过最大值 std::cout << check_overflow(2000000000) << std::endl; return 0; }
编译运行结果
- 未优化编译(-O0):运行输出
0(实际溢出后x变为负数,返回0) - 开启-O3优化:运行输出
1(编译器基于“无溢出”假设,认为x+1e9后仍>0,直接返回1)
内容的提问来源于stack exchange,提问作者ABu
相关产品推荐
相关产品推荐

