读取恰好具有良好值的未初始化变量
Reading uninitialized variable that happens to have a good value
我在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;
}
这意味着第一次运行时,我们正在读取一个未初始化的变量,这是未定义的行为。那么以下迭代呢?这仍然是未定义的行为吗?在嵌入式处理器上读取未初始化的变量时,我们可以看到什么样的行为?
遇到了一个未定义的行为,该行为和所有后续语句的行为也是未定义的。
矛盾的是,在未定义的语句之前的任何语句的行为也是未定义的。
至于行为类型,要求对未定义的行为进行分类是不合逻辑的。
是的,它是未定义的,但您观察到的行为并不一定令人惊讶; 只是堆栈被重用并且重用的空间没有初始化,并且您碰巧重用了与上次调用完全相同的堆栈位置。所有内存都必须包含一些东西,如果你调用这个函数,它碰巧重用与上一个调用相同的堆栈帧,它将包含最后剩下的任何内容。
例如,如果您调用:
Func() ;
Func() :
它没有定义,但第二次调用fooStruct.foo
包含第一次调用留下的值并非不合理,因为当编译器不执行任何操作来初始化变量时,就会发生这种情况。
但是,如果您拥有:
void Func2()
{
int x = 0 ;
int y = 0 ;
Func() ;
}
然后称为:
Func() ;
Func2() ;
由于堆栈帧用于Func2
,通过Func2()
对Func()
的第二次调用几乎肯定会将本地fooStruct.foo
放在堆栈中的不同地址,因此除了巧合之外不会具有相同的值。 此外,如果序列是:
Func() ;
Func2() ;
Func() ;
对Func()
的第三次调用可能使用与第一次相同的堆栈位置,但该空间可能已被Func2()
修改(由于初始化的变量),因此您可能不再在fooStruct.foo
中观察到相同的值。
这就是未初始化的意思;你得到任何碰巧在那里的东西。 而且因为当一个变量超出范围时,它通常不会被修改,这样的值可以"重新出现"(不一定在同一个变量中) - 只是因为这是最简单和最有效的实现(即什么都不做)。
- 初始值设定项列表是否只接受使用相同类型的值初始化变量?
- 在 C++ 中访问 lambda 捕获初始化变量
- 为什么C++不支持对未初始化变量进行智能分析?
- 使用 clang++ 和 g++ 在C++中初始化变量
- C++使用 lambda 初始化变量
- 如何在初始化列表中的构造函数之后初始化变量/对象?
- C++ - 输出与初始化变量不同?
- C++/Win32 构造函数不使用从对话框获取的字符串初始化变量
- 在C++中,为什么int可以使用new运算符初始化变量,而double不能
- 具有静态存储持续时间的常量初始化变量的初始化顺序
- C++ 中的初始化变量
- C++中未初始化变量的值
- 如何在需要提及需要循环声明的其他类的类中初始化变量?
- 我想知道在构造函数中初始化变量时的生命周期
- 读取恰好具有良好值的未初始化变量
- 如何在 getter 的父类中初始化变量的情况下访问子类中的变量
- 为什么在 c++ 中有多种初始化变量的方法
- 没有参数的默认构造函数是否总是初始化变量?
- 是否可以使用 lambda 初始化变量(删除复制 ctor 时)
- 使用构造函数跳闸UB的新放置后使用初始化变量