尝试了挺久才解决的,简单记录下过程中的一些思考:
现象:
程序hang/segment_fault的位置都是在同一个位置:一个lambda函数(会被注册为一个回调函数来使用), 类型大致是这样(有纯虚函数定义了回调函数的类型)
auto f = [&] () -> bool {
//some operation
//no return statement.
};
因为在编译的时候使用-Wp,-w, 这个选项会关闭预处理过程中的所有warning, 所以即使没有return语句也没有报错(程序在编译的时候是使用了-Wall的)
尝试:
- 既然O0是可以运行的,所以程序来逻辑/语法上肯定是没有问题的,所以就想着先把lambda函数关闭优化,可以使用__attribute__((optimize(“O0”))), 但问题在于我把这句挡在->bool之前的话会报错,所以我就试着把->bool给删除掉,然后在{}内显示的写了return true,函数调用处并不会使用这个return的值,所以return true/false倒无所谓。编译、运行,发现可以pass test。
1.1 试图查阅在lambda表达式中__attribute__应该放的位置,没找到。所以才投机取巧把->bool删除掉了。 - 进而我猜测不会是因为return语句导致的吧?于是就又把__attribute__((optimize(“O0”)))删掉,->bool加回来,然后return true, 编译、运行,test pass。
结论
其实没什么结论,也不理解为什么一个return语句会产生这样的问题,但给我的启示是:
- code要标准,要严格按照规范来,该return就return,就能减少遇到类似的问题。
- 要重视Warnings。这次遇到是因为Makefile从别的port过来的时候带了-Wp,-w, 把预处理器所有的Warning给关掉了。
更新01:
经过查阅资料,理解了为什么缺少return语句会产生这样的问题:
函数缺少 return 语句会导致未定义行为(undefined behavior,UB),这不仅会引发程序运行时的错误,还会影响编译器的优化过程。编译器在优化代码时,会基于一些假设进行,例如所有函数都按照其声明的返回类型返回值。如果某个函数缺少 return 语句,编译器的这些假设就会被打破,从而导致不可预测的行为。
- 当函数缺少 return 语句时,编译器可能会认为某些代码路径是不可达的(unreachable)。例如,GCC和Clang编译器会在这种情况下插入 __builtin_unreachable(),这会标记代码路径为不可达。
- 在优化过程中,编译器可能会移除这些不可达的代码路径,从而导致程序在运行时出现意外的行为。
并且,务必注意,不可预测的行为是指无法预测接下来会发生什么(而不是通常意义上的简单理解为返回随机值)。
参考:An example of undefined behavior caused by absence of return