【问题标题】:Does C++ initialize integers to zero automatically?C++ 是否自动将整数初始化为零?
【发布时间】:2015-10-02 01:50:23
【问题描述】:

我注意到几个影响很大的“未初始化标量变量”类型的 Coverity(静态分析工具)错误。其中很多只是未初始化的整数。

将它们初始化为零与默认情况下 C++ 所做的有什么不同吗?

【问题讨论】:

  • 我对这个问题进行了编辑以重新关注 C++。我主要在 C# 代码库中工作,但这些问题都在 C++ 代码中,抱歉之前不够清晰。
  • 嗯,int 是 c++ 和 C# 中的值类型,它们使用 X 字节的 ram,所有 0 位,它们都是 0。所以无论你是否初始化它们,在内存中它们仍然是 0 .
  • 它们是否被零初始化取决于它们的存储类型(静态或自动)以及它们的初始化方式。如果您发布完整的代码示例,可能会更容易回答。
  • 我无法发布任何代码示例(生产代码、保密协议、IP 等)——否则我会。我的很多挣扎都在问自己,“是否有一个安全/良好的默认值可以将 int 设置为?”。如果设置为 0 会发生什么?有时我发现没有好的默认情况,或者它可能会非常非常罕见地走上一条即使没有初始化也没有设置的路径。那么它只是不值得将它初始化为一个可能不是一个好的默认值。也就是说,我不希望这个问题沿着设计路径走,以确保它是一个清晰简洁的问题。
  • @PerryCampbell 问题是从未初始化的变量中读取是未定义的行为。因此,只要您在阅读之前将值设置为某个值,就可以了。

标签: c++ coverity


【解决方案1】:

C++ 会自动将整数初始化为零吗?

对于自动变量:

一些编译器可能会这样做,但标准并不要求这样做。符合标准的实现可能会使它们成为未初始化的垃圾值。

对于static 变量:

除非明确初始化,否则它们必须初始化为零。

【讨论】:

  • "有些编译器可能会这样做。"你确定吗? Clang、gcc 和 MSVC 都不会在 Release 版本中初始化标量。
  • MSVC 可以,我相信。它可能只在调试版本中(不确定),但这仍然很重要。
  • 在我看来,编译器永远不应该自动初始化变量,尤其是当它从一个构建更改为另一个构建时。这意味着您可能会遇到调试版本中没有出现的错误,这与要点无关
  • @celticminstrel 我猜你是对的,因为我没有看到任何意义。我说的是自动存储,顺便说一句。
  • @KABoissonneault 编译器在调试构建中初始化它们会非常有用。对于某些不太可能成为您想要的值:正如您所指出的,将它们初始化为 0 通常会产生反效果,但是将它们初始化为 0xDEADBEAF 或类似的东西是一个好主意(我认为这就是现代的MVS 确实)。
【解决方案2】:

默认情况下,C++ 不会将整数变量初始化为零。

在调试模式下编译您的项目时,某些编译器可能会将它们清零或填充一些默认值。在通常不会发生的发布模式下。

静态变量有一个例外,但默认情况下可以安全地假设任何未初始化的东西都包含一个随机值。

注意未初始化的变量。找到这种错误很难,而且会浪费很多时间。常见症状:程序在调试模式下运行良好,但在发布时表现异常。

【讨论】:

  • 但是这个呢? en.cppreference.com/w/cpp/language/zero_initialization好像说很多情况下int初始化为零?
  • 是的,很多情况,例如 static int myint;int myint = int(); 但不是普通的旧 int myint; 普通的旧 int myint; 未初始化为 0。
【解决方案3】:

在静态存储持续时间中声明的对象在任何其他初始化发生(包括默认初始化)之前初始化为零。

默认初始化T 类型的对象意味着:
— 如果 T 是(可能是 cv 限定的)类类型(第 9 条),则调用 T 的默认构造函数(并且 如果T 没有可访问的默认构造函数,则初始化格式错误);
— 如果T 是数组类型,则每个元素都是默认初始化的;
— 否则,不执行初始化
C.11 §8.5¶6

注意:每个静态存储持续时间的对象在程序启动时在任何其他初始化之前都被初始化为零 发生。在某些情况下,稍后会进行额外的初始化。 — 结束说明]
C.11 §8.5¶9

【讨论】:

    【解决方案4】:

    是和不是。

    这取决于它们是如何声明的。如果它们被声明为static,那么是的,它们保证被零初始化。但是,函数中的局部变量可能不是零初始化的。大多数情况下也不是类成员变量(static 除外)。

    基本上,如果不是static,你应该假设它不会被初始化为0。由于它没有被初始化,它可以有任何值。

    【讨论】:

    • 如果它不是静态的,默认初始化会使其未初始化,您不能假设任何事情。你甚至无法阅读它。
    • 我说的差不多吧?
    • 不,否则我不会评论。
    • 我没有说过你可以假设任何事情。原贴说的是初始化为 0,所以我重点说一下,但我没有说任何不正确的。
    【解决方案5】:

    影响很大的“未初始化标量变量”类型的错误

    是的,它们的影响很大,因为未初始化的自动变量具有不确定的值和using an indeterminate value is undefined behavior,因此如果您在初始化之前尝试从它们产生值,这些都是严重的错误。

    将它们初始化为零与默认情况下 C++ 所做的有什么不同吗?

    是的,对于自动标量变量,C++ 标准表示它们将具有不确定的值,来自8.5 部分的 C++ 标准草案 [dcl.init]

    如果没有为对象指定初始化器,则该对象是 默认初始化。当使用自动或 获取动态存储时长,对象有一个不确定的 值,并且如果没有对对象执行初始化,则 对象保留一个不确定的值,直到该值被替换 (5.17 [expr.ass])

    编译器可能在调试模式下初始化局部变量,以帮助调试,我们可以看到MSVC can do this using /RTC:

    将局部变量初始化为非零值。这有助于 识别在调试模式下运行时未出现的错误。[...]

    【讨论】:

      猜你喜欢
      • 2016-10-05
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 2021-04-05
      • 2016-02-01
      • 2021-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多