不从函数返回不是错误吗?

Not returning from a function is not an error?

提问人:Swift - Friday Pie 提问时间:11/7/2023 最后编辑:Swift - Friday Pie 更新时间:11/7/2023 访问量:122

问:

对于大多数主要编译器来说,gcc、clang、nvc 在编译以下代码(可抑制代码)时只产生警告的原因是什么?

#include <iostream>

int foo() { return 42; }   
int boo() { foo(); }

int main()
{
    std::cout << boo() << std::endl;
}

我们只是发生了一些事件,这些事件几乎没有以纯粹的运气导致人员丧生而告终,因为这些代码是硬件供应商代码(准确地说是自动驾驶仪)的一部分,我们无法更改。特定的编译器甚至没有产生警告(仅当函数中只有返回值时)。原文的推理是表达方式,没有意义,但我很难向监督者解释。{foo();}

更奇怪的是,在其他情况下,如果存在 eturn,编译器会产生错误。在这种情况下,只有诊断错误的编译器是 MSVC(几乎任何版本)。

C++ 未定义行为

评论

3赞 Quimby 11/7/2023
因为要求编译器强制函数始终返回 == 解决停止问题。因此,启发式生成警告是我们能得到的最好的方法。当然,例如,它可以抛出异常或调用,而不是触发未定义的行为,但这是一个单独的问题。std::terminate
1赞 Pepijn Kramer 11/7/2023
哎哟,似乎一些流程更改是有序的
1赞 KamilCuk 11/7/2023
that barely didn't end in a human life然后,您应该考虑 2012 年的 MISRA 规则 17.4 和 AUTOSAR 。安全标准的存在是有原因的。您提供的代码具有未定义的行为。编译器不需要对未定义的行为发出错误。使用没有返回值的函数返回值是未定义的行为。不返回的行为本身是可以的。仅当您尝试使用非返回函数的返回值时,它才会变得未定义。
1赞 Swift - Friday Pie 11/7/2023
@KamilCuk 可悲的是,错误的权威。除了规范结果之外,这里没有安全标准来规范这一点。non-void 函数返回。是的,我们的代码遵循这一点(并且只是通过编译器进行测试编译来做到这一点)。问题在于供应商库(与 MAVIK 相关),并且该标头包含类似缺少返回的函数之类的内容。不是我们的代码。在调试版本中,甚至按预期工作。getX()
1赞 KamilCuk 11/7/2023
它可能在调试版本中起作用,很可能是因为 from 填充了返回寄存器,然后由 读取。在优化的构建中,编译器将优化它,推断出未使用的内容并对其进行优化。return 42foo()main()return 42

答:

2赞 MSalters 11/7/2023 #1

问题在于编译器需要考虑一切。

零钱:

int foo() { throw 42; }   
int boo() { foo(); }

不寻常,但完全合法。中没有“缺少 return 语句”,但您需要知道它总是抛出。foofoo

这个想法并不完全牵强。如果被调用,你会期望它永远不会正常返回。foolog_and_throw<Exc>

评论

0赞 Swift - Friday Pie 11/7/2023
在这种情况下,我本来会认为 [[noreturn]] 存在......或者,如果它不合法,无一例外地支持(或案例),但是..井。。这种“不考虑”只是勉强花费了几千人的生命,并且由于这种措辞,一个写作的人是无懈可击的。
1赞 MSalters 11/7/2023
@Swift-FridayPie:在确实如此的行业中,你抓住像MISRA这样的东西,然后用它来打供应商。违反规则比编译器警告要糟糕得多。
0赞 Swift - Friday Pie 11/7/2023
我完全同意,尽管由于我们没有损失,而且这是测试环境(我们自己放弃了),而 MISRA 在这里没有法律效力,他们将没有苏格兰人。
1赞 463035818_is_not_an_ai 11/7/2023
int foo() { int x; std::cin >> x; if ( x == 42) throw 42; }这样一来,编译器就不可能知道调用是否正常。fooboo
0赞 James Kanze 11/7/2023
我会说这是一个实施质量问题。正如 @Swift-FridayPie 所指出的,我们确实有 -- 鉴于此,编译器警告函数是否且没有 ; 可以轻松关闭警告。[[noreturn]][[noreturn]]return[[noreturn]]
4赞 KamilCuk 11/7/2023 #2

不从函数返回不是错误吗?

越界访问数组不是编译错误,signed 溢出也不是编译错误,也不是编译错误。编译器不需要在代码中出现未定义的行为时出错。未定义的行为意味着没有要求 - 编译器可能会出错,可能不会,或者可能会产生鼻魔。fflush(stdin)

在 C++ 中,流向非 void 函数的末尾是未定义的行为。请参阅 https://stackoverflow.com/a/1610454/9072753 和在线草稿 https://eel.is/c++draft/stmt.stmt#stmt.return-4

评论

1赞 Swift - Friday Pie 11/7/2023
+1 报价。就我个人而言,我会说他们应该学习编程,而不是用霰弹枪射击。我有一个向每个人挥舞“奇怪文件”的名声,他们根本无法阅读它们。这些答案将是一个“外行术语”的东西,我可以添加到我自己的“意见”中,正如他们所说的那样。
1赞 Rodney 11/7/2023
这两个链接都是关于 C 的。问题是关于 C++ 的
1赞 KamilCuk 11/7/2023
哎呀,那副手法就无效了。编辑
0赞 MSalters 11/7/2023
我认为这有点不对劲。我认为这里的“X 不是编译错误”的想法是“允许使用符合 C++ 的实现,但不需要发出诊断”。如果运行时行为是不可避免的,则实现可能会另外拒绝编译代码。但这让我们回到了第一条评论,证明代码是否可访问与停止问题微不足道地等同。