10

我知道未定义的行为可能会导致任何事情,这使得任何包含 UB 的程序都可能毫无意义。我想知道是否有任何方法可以识别程序中未定义行为可能导致问题的最早点。这是一个例子来说明我的问题。

void causeUndefinedBehavior()
{
   //any code that causes undefined behavior
   //every time it is run
   char* a = nullptr;
   *a;
}


int main()
{
 //code before call
 //...
 causeUndefinedBehavior();
 //code after call
 //...
}

据我了解,可能引发(不一定表现出来)未定义行为的可能时间是:

  1. 什么时候causeUndefinedBehavior()编译。
  2. 什么时候main()编译。
  3. 程序运行时。
  4. 当时causeUndefinedBehavior()被执行。

或者对于每种情况和每种实现,未定义行为的触发点是否完全不同?

另外,如果我注释掉causeUndefinedBehavior()调用的行,那会消除 UB,还是因为编译了包含 UB 的代码,它仍然在程序中?

4

5 回答 5

4

正如您的代码所展示的那样,未定义的行为几乎总是尝试行为时的运行时状态条件。对您的代码稍作修改就会使这一点变得非常明显:

void causeUndefinedBehavior()
{
   //any code that causes undefined behavior
   //every time it is run
   char* a = nullptr;
   *a;
}


int main()
{
 srand(time(NULL));
 //code before call
 //...
 if (rand() % 973 == 0)
    causeUndefinedBehavior();
 //code after call
 //...
}

您可以执行一千次或更多次,并且永远不会触发 UB 执行条件。这并没有改变函数本身显然是 UB 的事实,但是在编译时在调用者的上下文中检测并不是微不足道的。

于 2012-10-29T00:30:11.867 回答
2

“未定义的行为”意味着语言定义没有告诉你你的程序会做什么。这是一个非常简单的陈述:没有信息。您可以根据自己的喜好推测您的实现可能会或可能不会做什么,但除非您的实现记录了它的作用,否则您只是在猜测。编程不是猜测。这是关于知道的。如果您的程序的行为未定义,请修复它。

于 2012-10-29T12:12:52.437 回答
2

我认为这取决于未定义行为的类型。会影响诸如结构偏移之类的东西可能会导致未定义的行为,这将在执行触及该结构的任何时间代码时显示出来。

然而,一般来说,大多数未定义的行为发生在运行时,这意味着只有在执行该代码时才会发生未定义的行为。

例如,修改字符串文字的尝试具有未定义的行为:

char* str = "StackOverflow";
memcpy(str+5, "Exchange", 8);    // undefined behavior

memcpy这种“未定义的行为”在执行之前不会发生。它仍然会编译成完全正常的代码。

另一个示例是省略具有非 void 返回类型的函数的返回:

int foo() {
    // no return statement -> undefined behavior.
}

在这里,正是在foo返回点发生未定义的行为。(在这种情况下,在 x86 上,eax寄存器中发生的任何事情都是函数的结果返回值。)

-Wall通过启用更高级别的编译器错误报告(例如,在 GCC上),可以识别其中许多场景。

于 2012-10-29T00:26:48.547 回答
1

虽然它是“未定义的行为”,但给定特定的编译器,它将具有某种可预测的行为。但是因为它是未定义的,在不同的编译器上,它可能导致在编译/运行时的任何时候发生这种行为

于 2012-10-29T00:26:56.167 回答
0

这使得任何包含 UB 的程序都可能毫无意义

不太对。程序不能“包含”UB;当我们说“UB”的缩写时:程序的行为是未定义的。所有的!

因此,该程序从一开始就不仅是潜在的,而且实际上是毫无意义的。

[intro.execution]/5:执行格式良好的程序的一致实现应产生与具有相同程序和相同输入的抽象机的相应实例的可能执行之一相同的可观察行为。但是,如果任何此类执行包含未定义的操作,则本国际标准对使用该输入执行该程序的实现没有要求(甚至不考虑第一个未定义操作之前的操作)。

于 2018-02-28T15:23:32.217 回答