1

我在 Blackfin 533 处理器上运行的一些代码中遇到了这个错误。

第一次Func()运行时,fooStruct将包含垃圾,但在下一次迭代中,getFoo()偶然返回的旧值仍然在fooStruct.foo.

FooStruct
{
    double foo;
    double bar;
};

void Func()
{
    FooStruct fooStruct;

    double bar = 123.4 / fooStruct.foo;

    fooStruct.foo = getFoo();
    fooStruct.bar = bar;
}

这意味着第一次运行时,我们正在读取一个未初始化的变量,这是未定义的行为。接下来的迭代呢?那仍然是未定义的行为吗?在嵌入式处理器上读取未初始化的变量时,我们可以期望看到什么样的行为?

4

2 回答 2

7

遇到了一种未定义的行为,该行为以及所有后续语句的行为也是未定义的。

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

至于那种行为,要求对未定义的行为进行分类是不合逻辑的。

于 2018-03-19T09:10:15.220 回答
4

是的,它是未定义的,但您观察到的行为并不一定令人惊讶;只是堆栈被重用并且重用的空间没有被初始化,并且您碰巧重用了与之前调用完全相同的堆栈位置。所有内存都必须包含一些东西,如果你调用这个函数并且它碰巧重用了与之前调用相同的堆栈帧,它将包含最后留下的任何东西。

例如,如果您致电:

Func() ;
Func() :

它没有定义,但第二次调用包含第一次调用留下的值并不是不合理的,因为当编译器不采取任何行动初始化变量 fooStruct.foo时会发生这种情况。

但是,如果您有:

void Func2()
{
    int x = 0 ;
    int y = 0 ;
    Func() ;
}

然后调用:

Func() ;
Func2() ;

由于 的堆栈帧,对Func()via的第二次调用几乎肯定会将本地放置Func2()在堆栈内的不同地址,因此除了巧合之外不会具有相同的值。此外,如果序列是:fooStruct.fooFunc2

Func() ;
Func2() ;
Func() ;

第三次调用Func() 可能使用与第一次相同的堆栈位置,但该空间可能已被修改Func2()(因为已初始化的变量),因此您可能不再在fooStruct.foo.

这就是未初始化的意思;你会得到那里发生的任何事情。并且因为当一个变量超出范围时,它通常不会被修改,这样的值可以“重新出现”(不一定在同一个变量中)——因为这是最简单和最有效的实现(即什么都不做)。

于 2018-03-19T12:15:32.603 回答