3

有时,我们可以使用 valgrind 之类的工具来找出是否忘记初始化指针变量。但是,为什么现代编译器不能让我们摆脱这种难以重现的常见错误呢?

4

3 回答 3

4

初始化并不总是可取的:

  • 出于性能原因;初始化内存需要时间,这可能不是必需的。甚至有一些算法依赖于恒定的时间分配来实现其所需的性能(初始化是线性时间)。D 认识到这一点,但有不同(可能更好)的方法;变量默认初始化,但有特殊的语法来防止初始化。

  • 有时没有正确的默认值。静态分析或运行时调试功能可以帮助检测何时使用变量而不进行初始化。默认情况下简单地为它们分配一些(不正确的)值可以隐藏使用这些检测到的错误。

于 2013-02-16T04:33:20.183 回答
2

你的问题有几个方面。首先,该标准不强制要求这种行为。但是在不违反标准的情况下,它可能是可能的。事实上,调试构建,例如在 MSVC 中,做的完全相反,初始化不是0用一些魔法值而是用一些魔法值——另一个魔法值用于填充“释放”的内存。同样,这是特定于调试版本的,可以帮助检测某些类别的错误,同时它可能隐藏其他错误或模糊代码库中的位置。

但我认为性能问题在这里更重要。如果要初始化整数和浮点数,为什么不在堆和堆栈上都使用各种结构或数组呢?问题当然是如果我编写程序并分配一个缓冲区来读取数据,如果我知道我要读取 x 个字节并且缓冲区只有 x,为什么还要浪费时间先将缓冲区归零字节长?

我同意,像在 Debian SSH 灾难中那样依赖这种“随机”行为是不正确的,但它表明人们依赖于现有的行为,而改变这种行为的后果并不总是显而易见的。

于 2013-02-16T04:35:59.673 回答
0

不完全是。除了其他答案中提出的原因外,我想指出:

a) Global variables, static local variables are always initialized, if not explicitly, then implicitly zero.
b) For a custom class `class Test`, creating a new instance by `Test *ptr=new Test()` or `Test test;` gives an initialized object.

总而言之,ELF 文件的 '.data' '.bss' 部分中的内容被显式或隐式初始化(​​零)。不在上述区域中的原始类型中的其他变量在显式初始化之前具有未定义的内容(取决于您的编译器)。这是因为,ELF 文件本身提供了a)一种以非常低的成本以实物形式初始化变量的方法,而在堆栈、堆等中初始化变量可能是一个可怕的开销。

您可能会争辩说,class Object初始化的成本可能更高。但是,最重要的是,省略原始类型的初始化是 C 中的工作方式,因此 C++ 遵守它。

于 2013-02-16T05:43:07.463 回答