【问题标题】:Is C++ compiler obligated to generate 'ret' instruction for a function without 'return' statement?C++ 编译器是否有义务为没有“return”语句的函数生成“ret”指令?
【发布时间】:2021-11-18 20:18:57
【问题描述】:

最近我遇到了一个问题,我的程序中的一个线程以某种方式停止(GDB 指示线程的状态为 STOPPED)。我花了几天时间调试。几天前我更改了编译器的版本后发生了这个问题。最后我发现问题的发生是因为一个函数是用int 返回类型定义的,但没有return 语句。所以函数的asm代码没有ret指令。当它在运行时到达函数的末尾时,由于不存在ret 指令,因此继续执行另一个函数中的下一条指令。这会导致线程被停止。我查过之前版本编译器生成的asm代码,同样的函数确实有ret指令。

根据我的经验,不建议在具有非 void 返回类型的函数中缺少 return 语句,但不应导致提前停止。我想知道是我错了,还是编译器错了。

我的问题是,对于具有非 void 返回类型的正常结束(非异常、调用、jmp...)函数,编译器是否有义务生成 ret 指令。它是否有任何 C++ 标准或 C++ 规范说明这种情况下的编译器行为?

我进行了一些搜索,并在 this 中找到了 c# 的答案。 C++ 怎么样?

【问题讨论】:

  • 一般来说,该标准并没有规定具体的 asm 指令。它只定义行为。
  • @HolyBlackCat 或者在这种情况下没有定义行为

标签: c++ return


【解决方案1】:

没有。

对于除 main 之外的任何非 void 函数,如果通过函数的任何路径不是 return,如果在运行时采用该路径,则您的程序会表现出未定义的行为。然后允许编译器做任何感觉。通常这只会导致缺少 ret 语句,但我看到了更奇怪的效果。

标准在 [stmt.return].2 中指定了这一点:

[..] 从构造函数、析构函数或 具有 cv void 返回类型的非协程函数等价于 返回没有操作数。 否则,从函数的末尾流出 除 main (6.9.3.1) 或协程 (9.5.4) 以外的结果未定义 行为

(强调)

【讨论】:

  • "如果有任何通过该函数的可达路径" AFAIK 必须实际采用该路径才能导致 UB。例如。 int foo(bool x) {if (x) return 42;} 不是 UB,直到您实际调用 foo(false);
  • @HolyBlackCat 是的,那个措辞是错误的,谢谢。我的意思是在运行时可达。让我更正一下。
  • 这是什么标准?查看draft,应该是stmt.return.4
  • @OlafDietsche 我以为我面前有 C++20 标准(草案):isocpp.org/files/papers/N4860.pdf
  • @WenwenKang -- “未定义的行为”意味着标准没有告诉你程序做了什么。推测编译器可能生成什么代码以及它的行为通常是没有意义的。
猜你喜欢
  • 2017-09-04
  • 2011-05-14
  • 1970-01-01
  • 2014-10-15
  • 2021-08-15
  • 2018-06-08
  • 1970-01-01
  • 2016-05-08
  • 2011-03-25
相关资源
最近更新 更多