这是未定义的行为,你如何判断
Is this undefined behavior and how would you tell?
被这篇文章的回复所激励。为什么是NaN
我有以下代码:
int main()
{
const int weeks = 10;
const int salespersons = 9;
const int days = 30;
double weekly_sales[weeks][salespersons][days];
double total_weekly_sales[weeks];
double total_overall_weekly_sales[salespersons];
int a;
cout << "a = " << a <<endl;
cout << total_weekly_sales[0] <<endl;
for(int w=0; w < weeks;w++)
{
for(int d =0; d < days; d++)
{
for(int s=0; s < salespersons; s++)
{
total_weekly_sales[w]+=weekly_sales[w][s][d];
total_overall_weekly_sales[s]+= weekly_sales[w][s][d];
}
}
}
cout << total_weekly_sales[0] <<endl;
}
它将输出如下内容:
a = 0
0
0
在gcc 4.5.3下,带有编译选项-Wall
.
我还编译了下面的代码:http://liveworkspace.org/code/94SOj$2。输出与上面相同
我还在VS2010下编译了代码。VS2010给出如下警告:
warning C4700: uninitialized local variable 'a' used
warning C4700: uninitialized local variable 'total_weekly_sales' used
当我跑步时:
Run-Time Check Failure #3 - The variable 'a' is being used without being initialized.
我知道不初始化局部变量并使用它们是不好的做法。我也知道这会有问题。
我的问题是:在c++标准中:是否有任何地方说使用未初始化的局部变量会导致未定义的行为?为什么它在不同的编译器下表现不同?这是否意味着标准实际上没有强制所有编译器都应该实现有关using uninitialized local variable
的适当动作?如何从编译器输出告诉它是未定义的行为?
谢谢。
是的,标准明确规定未初始化对象的左值到右值转换将导致未定义的行为:
非函数、非数组类型
T
的glvalue(3.10)可以转换为右值。如果T
是不完全类型,则需要进行这种转换的程序是病态的。如果glvalue所指向的对象不是T类型的对象,也不是T派生类型的对象,或者该对象未初始化,则需要进行这种转换的程序具有未定义行为。
任何需要使用object的值的操作都将调用左值到右值的转换。
未定义行为定义为:
本国际标准未规定的行为
所以,是的,具有未定义行为的程序可以做任何事情,即使它看起来工作正常。因此,您不能总是从程序输出中识别未定义的行为。真正的解决方案是编写正确的、定义良好的代码。要做到这一点,我强烈建议您身边有一份c++标准的副本。编写代码并对其功能进行假设是一件非常糟糕的事情,所以如果你编写了任何你不确定的c++,一定要检查它。
为什么标准中存在未定义的行为?首先,这意味着你只会得到你想要的。如果将未初始化的变量定义为自动获取值0(例如),则您声明的每个未初始化的变量都将进行一些可能不需要的额外操作来将值设置为0。该标准简单地说,使用未初始化变量的值是未定义的,允许它在该内存位置留下已经存在的垃圾值。不额外收费。
其次,它允许编译器基于任何c++程序员都会编写相同的、定义良好的代码的假设来进行优化。
未定义行为就是这个意思。行为是未定义的。有些编译器会很好地警告你,有些则会做一些疯狂的事情。理论上,他们允许在这种情况下擦除你的硬盘驱动器,但这将是一个相当糟糕的编译器。
更具体地说,未初始化的变量可以有任何值。实际上,如果您的程序刚刚启动(操作系统提供的一种安全特性,用于阻止您的程序从旧程序中读取内存),它通常为0,但是一旦它运行了一段时间,它很有可能是一个完全随机的值,因为内存以前被另一个函数使用过。因此发出了警告。如果您忽略它,您的程序将随机失败,没有明显的原因。
- 如何判断SSL_read是否已经接收并处理了来自单个消息的所有记录
- 如何判断类型双关语在我的平台上是否可以?
- 失败,出现错误 87:参数不正确.如何判断哪个参数不正确?
- 如何判断是否在编译时计算了"constexpr"(无需手动检查)
- 如何构造一个类型特征,可以判断一个类型的私有方法是否可以在另一个类型的构造函数中调用?
- 如何判断指针是否是指向数组的指针
- C++如何判断互斥体在阻塞其他线程时是否被单个线程不成比例地占用
- 如何判断 c++ 向量中的值类型(整数或双精度)?
- 通过 pid 窗口判断进程是否存在
- 如何判断我正在运行的Microsoft C++代码是否使用 /EHa 开关编译?
- 如何判断是否有另一个线程试图保持互斥锁?
- 编写一个函数,该函数将通过判断其每个参数的类型来自动确定其返回值
- 如何通过其手柄判断堆是否序列化
- 如何判断我的过程中的哪个模块创建了哪个堆
- 如何判断从 CreateProcess 启动的进程是否仍在运行
- boost::P rogram_options 一种判断值是从命令行还是 ini 文件的方法?
- 如果有办法判断编译器是否真的内联C++函数
- 如何判断虚拟内存页是否已锁定
- 如何判断类型是否是特定模板类的实例
- 判断 int 是否在 C++ 中赋值的任何优雅方法