如果程序的一部分表现出未定义的行为,它是否会影响程序的其余部分?

假设程序员忘记初始化他的一个自动变量,并且他使用了它的值,从而调用了未定义的行为。

... int i = 0, j; ... printf("value of 'j': %d\n", j); ... ... char buf[256]; fputs("Enter query:", stdout); fgets(buf, sizeof(buf), stdin); ... //process input ... perform other tasks 

程序员在屏幕上注意到乱码,并意识到他的程序是错误的,但它并没有崩溃,反正还在继续。

假设在此之后,程序提示用户输入并期望处理它,显示结果并执行所有独立于未初始化变量的其他任务,是程序员鼓励停止使用程序,修复错误,重新编译和运行? 该计划的其余部分是否会不一致?

一旦达到具有未定义行为的语句,则整个程序的行为是未定义的。

矛盾的是,之前运行的语句的行为也是未定义的。

未定义的行为仅仅是编程语言缺乏保证。 但是当然可能有其他事情要求程序行为,甚至是确定性的方式,例如记录的编译器扩展或操作系统和CPU行为。

因此,您无法从编程语言的角度来推断未定义的行为。 该语言将简单地说所有赌注都已关闭,并且不保证程序的任何行为。

考虑到特定的系统,您可以推断出会发生什么。 如果这是一个有意义的事情,那就是另一个故事。

在您的具体示例中,典型的系统可能只会打印一些垃圾,并且程序的其余部分不太可能受到影响。 但是UB的情况并非总是如此。

一旦有了UB,那么没有任何好处可以预期。 标准说它。

n1570-3.4.3(P2):

可能的未定义行为包括完全忽略不完整结果的情况,在翻译或程序执行期间以环境特征(有或没有发出诊断消息)的特定文档执行,终止翻译或执行(发布时)一条诊断信息)。

此行为适用于整个程序。

标准假定程序在“抽象机器”上运行,在任何标准不强制要求的情况下,程序可能以最无理由的方式随意行事,包括时间旅行。 在C标准没有要求的许多情况下,许多真实世界的实现都针对真实机器,其行为被定义和记录。 不幸的是,一些编译器编写者很清楚,当他们的编译器将会或者不会以与序列执行程序的所有步骤一致的方式运行时,以及何时它将会或者不会暴露环境的特征行为标准允许但不要求它这样做。

如果编译器指定它如何存储int类型的自动对象,并且这些类型没有陷阱表示,那么这样的规范也可能意味着如果实现的生成代码始终与该规范一致,上述代码将如何表现。 问题在于许多实现定义了它们如何存储各种对象,但没有指出它们是否以这种方式一致地存储它们,或者仅在标准需要它的情况下存储它们。