最近我遇到一个问题,程序中的一个线程不知何故停止了(GDB 指示线程的状态为“已停止”)。我花了几天时间调试。这个问题是前几天换了编译器版本后出现的。最后我发现问题的发生是因为一个函数定义了int返回类型但没有return声明。所以该函数的asm代码没有指令ret。当它在运行时到达函数末尾时,由于不ret存在指令,因此继续执行另一个函数中的下一条指令。这会导致线程停止。我检查了以前版本的编译器生成的asm代码,同样的函数确实有一条ret指令。
根据我的经验,return不建议在具有非 void 返回类型的函数中缺少语句,但不应导致 ad 停止。我想知道是我错了,还是编译器错了。
我的问题是,对于具有非 void 返回类型的正常结束(不是由异常、调用、jmp... 结束)函数,编译器是否有义务生成指令ret。是否有任何 C++ 标准或 C++ 规范说明了这种情况下编译器的行为?
我做了一些搜索,并在此找到了 c# 的答案。对于 C++ 来说怎么样?
不。
对于除 main 之外的任何非 void 函数,如果存在通过该函数的任何路径不return,则如果在运行时采用该路径,则程序会表现出未定义的行为。然后编译器就可以做任何它想做的事情。一般来说,这会导致缺少 ret 语句,但我看到了更奇怪的效果。
标准在[stmt.return].2中指定了这一点:
[..] 从构造函数、析构函数或具有 cv void 返回类型的非协程函数的末尾流出相当于没有操作数的返回。否则,从 main (6.9.3.1) 或协程 (9.5.4) 以外的函数末尾流出会导致未定义的行为。
(强调已添加)