我的gtk程序在从debug模式切换到release模式后,运行文件扫描,之后崩溃。但是debug模式就不会崩溃。
我先是在程序里加了一些测试语句,输出,发现是在一个回调函数执行的时候导致崩溃
只打印了info 1,没有打印info 2
就进入哪个回调函数,在这个函数里加了测试输出语句,我发现这个回调函数在执行结束后依旧没有任何问题,是正常输出了测试语句然后退出的。我就不知道是什么原因了。
void function(){
std::cout<<"info a\n";
...
std::cout<<"info b\n";
...
std::cout<<"info c\n";//执行完这个语句代表正常结束退出
}调用它的地方执行失败,但是它本身执行完成了。输出是这种
info 1
info a
info b
info c
我测试了回调函数指针也不是空指针。
后来我就想,Mingw并不区分debug和release模式,只不过是编译参数的区别,我检查了IDE的编译参数,发现debug版本有的编译参数和release版本的区别就是,debug版本多了这两个参数:-g3 -D__DEBUG__
release版本多了这个参数:-O2,这是一个优化参数,我尝试去掉-O2参数,发现运行就不崩溃了。
-O2会更激进的优化代码,根据我的理解就是使用这个参数后编译器认为你的代码写的非常合理,不会导致一些未定义行为,就极端优化掉一些代码。导致造成解引用空指针之类的问题。
就比如
#include <stdio.h>
int main() {
int *p = NULL;
int x = (p != NULL) ? *p : 0; // 潜在空指针解引用
printf("%d\n", x);
return 0;
}
//-O0:可能侥幸运行(未实际解引用)。
//-O2:直接优化掉条件判断,导致段错误。(1) -O0(无优化)
- 编译器会 严格按照代码字面意思 生成指令:
- 检查
p != NULL。 - 如果为假,直接跳转到赋值
0的分支。 - **不会实际执行
*p(因为条件为假)。
- 检查
- 结果:程序侥幸运行,输出
0。
(2) -O2(激进优化)
- 编译器会进行 逻辑推断:
- 它发现
p被明确初始化为NULL,且后续未被修改。 - 因此
p != NULL永远为假,整个条件表达式等价于0。 - 优化后的逻辑:
- 但某些编译器版本会进一步推断:
- "既然
p是NULL,那么*p是未定义行为(UB)"。 - 根据 C 标准,编译器可以假定程序不会触发 UB,因此直接优化掉整个分支。
- 最终可能生成:
- 或者更激进的版本可能直接 删除整个代码块(因为 UB 允许编译器做任何事)。
- "既然
- 它发现
所以我这种编程没有太规范的人还是老老实实用-O0吧。