【问题标题】:Is there any way to predict the undefined behaviour or implementation defined behaviour?有没有办法预测未定义的行为或实现定义的行为?
【发布时间】:2011-12-10 08:10:03
【问题描述】:
#include<stdio.h>
int main(void)
{
    int i=5;
    printf("%d", i++ + ++i);
    return 0;
}

我知道这是未定义的行为(或已定义的实现),不应使用。但是编译器确实给出了一个输出而没有给出任何警告。那么有没有可以预测程序的输出呢?

【问题讨论】:

  • 如果“预测未定义的行为”是指“它可以做任何事情”。那么是的。
  • 我认为这就是我们称之为未定义行为的部分原因......这可能并不容易预测,尤其是从一般的角度来看。
  • 当然,通过了解具体实现版本的内部,将环境、标志和其他设置考虑在内。
  • @PlatinumAzure,实际上不可能静态预测 UB - 考虑void foo() { int *p = NULL; runTuringMachine(); *p = 1; }。如果runTuringMachine() 停止,我们有未定义的行为;否则我们不会。因此解决UB是否存在的问题需要解决停机问题,这是不可能的。当然在现实中runTuringMachine() 可能会填写p 的值...
  • 什么?这太荒谬了——你可以证明调用任何两个操作是合理的,其中一些操作由于停止问题而无法预测。未定义的行为通常以声明性、上下文无关的方式解释:分配给空指针地址是未定义的行为,无论它是否被执行。它仍然会有未定义的行为;这取决于正在执行的代码,这首先是 behavior 定义的一部分。

标签: c operators


【解决方案1】:

有没有办法预测未定义的行为

未定义的行为意味着编译器不需要遵守任何特定的行为,每个编译器可能会或可能不会显示相同的行为。您不能依赖编译器的未定义行为的近似/预测输出并在此基础上编写代码。

严格来说,避免编写任何调用未定义行为的代码。

参考:

未定义行为 (UB) 由 ISO/ANSI C 标准定义为:

在使用不可移植或错误程序结构、错误数据或不确定值对象时的行为,本国际标准对此没有要求。
注意:可能的未定义行为范围从完全忽略具有不可预测结果的情况,到在翻译或程序执行期间以环境特征的记录方式表现(有或没有发出诊断消息),到终止翻译或执行(发出诊断消息)

有什么方法可以预测实现定义的行为

是的,如果可移植性(确保您的解决方案以相同的方式在不同编译器中工作)不是您关心的问题。
不,如果您正在寻找便携性。

如果您正在使用特定的编译器,并且您的解决方案/项目只需要适用于该特定的编译器和环境,那么您可以冒昧地使用该编译器显示的特定于实现的行为该环境下的编译器。


这应该是一个有趣的阅读:

A Guide to Undefined Behavior in C and C++.

【讨论】:

  • 请注意,如果您知道将在哪个编译器上编译,您可以依赖实现定义的行为。此外,一些编译器/操作系统也可能会自行定义未定义的行为。
  • @bdonlan:不是便携式的。
  • 当然。正如我所说,您必须知道您将在哪个编译器上进行编译。当然,实际上这种情况一直都在发生——您必须使用一些操作系统定义的 API 来显示 GUI,或使用网络调用,此时您可以采用其他选定的实现定义的假设(例如,您可以假设Windows 程序中的 twos-compliment 溢出)
  • @bdonlan: 在某些情况下,是的,您可以依赖编译器实现定义的行为。但是对于新用户便携性这是一个严格的否。
  • @all 关于这个问题,有人说它总是给出偶数。有人解释说计算是从右手边开始的?
【解决方案2】:

静态源代码分析器(例如,某些配置下的 PC-Lint、Coverity Prevent、GrammaTech Code Sonar 等)可检测大多数未定义行为的情况,如您所述。

【讨论】:

    【解决方案3】:

    如果您使用的是 GCC,则可以使用 -Wall 提高警告级别(打印更多警告)。其他编译器可能也有类似的设置。

    【讨论】:

      【解决方案4】:

      一些编译器在发出警告方面做得越来越好。例如,对于 gcc 4.5(但 不是 与 4.3,并且绝对不是 CentOS 5 使用的 4.1),对于代码:

      void foo(int i)
      {
         int a = i   + i++;
         int b = i   + ++i;
         int c = ++i + i;
         int d = i++ + i;
         int e = ++i + i++;
         int f = i++ + ++i;
         int g = ++i + ++i;
         int h = i++ + i++;
      }
      

      gcc 将为正文的八行中的每一行给出消息:

      warning: operation on 'i' may be undefined
      

      但 Clang 静态分析器(从今年 1 月开始)没有。

      【讨论】:

      • 编辑:MSVC10 也没有给出关于 UB 的任何警告。
      猜你喜欢
      • 2011-05-20
      • 2011-11-06
      • 1970-01-01
      • 1970-01-01
      • 2011-01-19
      • 1970-01-01
      • 2021-10-14
      • 1970-01-01
      相关资源
      最近更新 更多