我想检查gcc
的优化选项如何影响程序,代码是这样的:
#include <iostream>
class A {
public:
A() {
a[0] = 10;
a[1] = 20;
empty;
}
int a[5];
bool empty;
};
int main(void){
A a;
std::cout << a.empty << std::endl;
return 0;
}
由于empty
成员在构造函数中没有赋值,我希望它是一个随机值。编译并运行它:
# g++ -g test.cpp
# ./a.out
254
# ./a.out
254
# ./a.out
253
# ./a.out
253
结果如我所料。然后我使用-O2
编译选项:
# g++ -g -O2 test.cpp
# ./a.out
0
# ./a.out
0
# ./a.out
0
# ./a.out
0
似乎总是0
。我使用gdb
来调试程序:
14 int main(void){
(gdb) n
17 std::cout << a.empty << std::endl;
(gdb) p a
$1 = {
a = {[0] = 10, [1] = 20, [2] = <optimized out>, [3] = <optimized out>, [4] = <optimized out>},
empty = <optimized out>
}
我只是想确保empty
是optimized out
,它的值也应该是随机的,是不是?
答案 0 :(得分:2)
我理解为什么你可能认为它应该是随机的,但你要求的是具有某些特征的垃圾值。换句话说:您希望定义未定义的行为。对不起,但你无法提出要求!当你对世界上所有计算机求平均值时,它是随机的。不是你的小笔记本电脑上的特定小程序。这与在单台计算机上不容易发现random errors的原因相同,因为它们在许多计算机上的许多用途中都是随机的。
答案 1 :(得分:1)
未初始化的价值就是:未经初始化。它们具有内存中该位置的值。多次运行可能相同,也可能是“随机”运行。它取决于它所在的内存位置,以及该内存中的值,以及在调用当前函数之前已经进行了哪些其他调用以及它们操作的数据。在这种情况下,您的代码位于main
,因此main
之前的调用变化不大(除非您更改系统,交换编译器等)。
在某些系统上,对于某些数据类型,可能会导致陷阱 - 或者因为未初始化的数据具有错误的奇偶校验值,或者因为值本身无效(例如,尝试加载具有无效组合的浮点数)当地址的段部分不是有效的段描述符索引时,在受保护模式x86系统上加载“远”指针,等等)
“非确定性”不仅仅是“随机” - 没有办法查看代码来确定值应该是什么。但认为它应该是随机数的良好来源是不正确的。基于之前发生的事情,它经常是“可猜测的” - 只需要知道“我们是如何到达这里的,以及在路上发生的事情”,而不是仅仅读取源代码中的值来确定它的值是什么