在C89(又名ANSI C)中省略return语句未定义的行为?

Grz*_*ski 15 c c89 language-lawyer

考虑以下基本示例:

#include <stdio.h>

int main(void)
{
    printf("Hi there!\n");
}
Run Code Online (Sandbox Code Playgroud)

它是否在C89中调用未定义的行为?我试图从这个问题中得到一些意义,但是大多数赞成的答案声称它是实现定义的,绝对没有UB(与Keith Thompson的评论,看起来相互矛盾).

规范在§3.16 定义和惯例中说明:

如果违反约束之外出现的"应"或"不应"要求.行为未定义.未定义的行为在本国际标准中以"未定义的行为" 或省略任何明确的行为定义来表示.这三者之间的重点没有区别:它们都描述了"未定义的行为".

和§5.1.2.2.3 程序终止:

从初始调用到main函数的返回等效于使用exit函数返回的值main作为其参数调用函数.如果main函数执行不指定值的返回,则返回到主机环境的终止状态是未定义的.

我的理解是,后面的子条款不包括丢失返回的情况,因为return声明从未被调用过,因此以前的子条款适用.

然而futher读数表明不同的东西,§6.6.6.4 return声明:

如果执行了return没有表达式的语句,并且调用者使用了函数调用的值,则行为是未定义的. 到达}那个终止函数等同于执行return没有表达式的 语句.

好的,所以现在的5.1.2.2.3子条款适用:

如果main函数执行不指定值的返回.返回到主机环境的终止状态是未定义的.

术语"终止状态未定义"似乎不是UB,也不是任何特定行为,但更像是在C标准范围之外,更像是:"让主机环境变得烦恼,我们洗手这里".这是正确的解释吗?

Jam*_*mes 4

几年前,我实际上调试了由此引起的问题。如果您有一些带有返回值而另一些则没有返回值的代码路径,它会变得更加有趣。

正如 @aruisdante 在评论中推测的那样,所表现出的行为确实是“未定义”的,但唯一未定义的部分是返回的值(它不像许多其他可能导致程序崩溃的“未定义”情况)。

如今,这实际上构成了安全风险,因为返回的“未定义”值通常是通常用于返回值的 CPU 寄存器中(或在某些实现中的堆栈上)中发生的任何值,理论上这可用于泄漏敏感数据。