提问人:Swift - Friday Pie 提问时间:11/7/2023 最后编辑:Swift - Friday Pie 更新时间:11/7/2023 访问量:122
不从函数返回不是错误吗?
Not returning from a function is not an error?
问:
对于大多数主要编译器来说,gcc、clang、nvc 在编译以下代码(可抑制代码)时只产生警告的原因是什么?
#include <iostream>
int foo() { return 42; }
int boo() { foo(); }
int main()
{
std::cout << boo() << std::endl;
}
我们只是发生了一些事件,这些事件几乎没有以纯粹的运气导致人员丧生而告终,因为这些代码是硬件供应商代码(准确地说是自动驾驶仪)的一部分,我们无法更改。特定的编译器甚至没有产生警告(仅当函数中只有返回值时)。原文的推理是表达方式,没有意义,但我很难向监督者解释。{foo();}
更奇怪的是,在其他情况下,如果存在 eturn,编译器会产生错误。在这种情况下,只有诊断错误的编译器是 MSVC(几乎任何版本)。
答:
2赞
MSalters
11/7/2023
#1
问题在于编译器需要考虑一切。
零钱:
int foo() { throw 42; }
int boo() { foo(); }
不寻常,但完全合法。中没有“缺少 return 语句”,但您需要知道它总是抛出。foo
foo
这个想法并不完全牵强。如果被调用,你会期望它永远不会正常返回。foo
log_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; }
这样一来,编译器就不可能知道调用是否正常。foo
boo
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++ 的实现,但不需要发出诊断”。如果运行时行为是不可避免的,则实现可能会另外拒绝编译代码。但这让我们回到了第一条评论,证明代码是否可访问与停止问题微不足道地等同。
评论
std::terminate
that barely didn't end in a human life
然后,您应该考虑 2012 年的 MISRA 规则 17.4 和 AUTOSAR 。安全标准的存在是有原因的。您提供的代码具有未定义的行为。编译器不需要对未定义的行为发出错误。使用没有返回值的函数返回值是未定义的行为。不返回的行为本身是可以的。仅当您尝试使用非返回函数的返回值时,它才会变得未定义。getX()
return 42
foo()
main()
return 42