请考虑以下基本示例:
#include <stdio.h>
int main(void)
{
printf("Hi there!\n");
}
它是否在C89中调用未定义的行为?我试图从this question得到一些理解,但大多数赞成的答案都声称它是实现定义的,绝对没有UB(带有Keith Thompson的评论,看起来很矛盾)。
规范在§3.16定义和惯例中说明:
如果“必须”或“不应”要求出现在a。之外 约束被违反。行为未定义。未定义的行为 在本国际标准中另有说明 “未定义的行为”或遗漏任何明确的定义 行为即可。这三者的重点没有区别:他们 所有这些都描述了“未定义的行为”。
和§5.1.2.2.3程序终止:
从初始调用到
main
函数的返回相当于 使用exit
函数返回的值调用main
函数 作为其论点。如果main
函数执行指定的返回 没有值,返回主机环境的终止状态是 未定义。
我的理解是后面的子条款不包括丢失返回的情况,因为return
语句从未被调用过,因此以前的子条款适用。
然而,进一步阅读表明存在不同之处,§6.6.6.4 return
陈述:
如果执行没有表达式的
return
语句,则返回值 调用者使用函数调用,行为未定义。 到达终止函数的}
等同于执行a 没有表达式的return
语句。
好的,现在5.1.2.2.3
子条款适用:
如果
main
函数执行指定的返回 没有价值。返回到主机环境的终止状态是 未定义。
术语“终止状态未定义”似乎不是UB,也不是任何特定行为,但更像是在C标准范围之外,更像是:“让主机环境要担心,我们从这里洗手“。这是正确的解释吗?
答案 0 :(得分:4)
多年前,我实际调试了由此引起的问题。如果你有一些返回的代码路径而没有返回的代码路径会更加有趣。
正如@aruisdante在评论中所推测的那样,展示的行为确实是“未定义的”,但唯一未定义的部分是返回的值(它不像其他许多&#39; undefined&# 39;可能导致程序崩溃的情况。)
这些天这实际上构成了安全风险,因为未定义的&#39;返回的值通常是通常用于返回值的CPU寄存器(或在某些实现中的堆栈上),理论上可用于泄漏敏感数据。
答案 1 :(得分:2)
我认为标准委员会的意图是此终止状态值未指定。
根据N739草案:
并改变子条款5.1.2.2.3的最后一句:
如果/ main /函数执行一个不指定值的返回, 返回到主机环境的终止状态为未定义。
为:
如果/ main /函数执行不指定值的返回,|返回到主机环境的终止状态是 的不确定强>
[其他地方小心避免使用未定义值的概念。]
您可能还会在进一步的标准中发现,术语已更改,因此使用术语“未指定”。
我会说它本身并不打算成为未定义的行为,但仍无法确定它是否是未指明的行为,或者我根本没有说过任何行为。其他摘录,表明后者是§1范围:
本国际标准未规定:
- 调用C程序供数据处理系统使用的机制;
我希望这也意味着本国际标准没有规定主机环境如何处理程序的终止状态。