强制局部变量默认初始化

时间:2012-12-01 15:59:33

标签: c++

在C ++中,默认情况下,普通旧数据(POD)局部变量未初始化。我注意到,这会导致错误,因为尝试读取未初始化变量的值是未定义的行为。

有没有办法强制编译器自动初始化所​​有局部变量?也许是内置此功能的编译器,或者是GCC或Clang之类的常见编译器的编译器开关? Gnu扩展我会没事的;它不一定是标准的。

我希望变量是默认初始化的,这意味着int将被设置为0.

我很无聊将所有本地int和私有类字段分配给0。

2 个答案:

答案 0 :(得分:1)

我不知道该做的任何事情,即使它 did 存在,它也只是一个“调试”功能,不能在生产代码中使用。

示例:电子围栏库可以选择将内存初始化为0或0xff

  

EF_FILL       当设置为0到255之间的值时,分配的内存的每个字节都会初始化为该值。这可以帮助检测未初始化内存的读取。设置为-1时,某些内存将填充为零(大多数系统为操作系统默认值),并且某些内存将保留上次使用时写入该内存的值。

(仅适用于已分配的内存,不适用于自动内存)。

依靠未定义为/未在标准中定义的开关将使您的代码不可移植。在某些时候,有人会使用您的代码在其他平台上交叉编译它,这将会失败。

作为帮助/保护措施,某些工具,例如Coverity(注意:我与该公司无关)可以检测代码中未初始化的POD成员。可能有免费的工具可以做到这一点。

那么如果有一个或两个POD成员(c ++ 11),我该怎么办:

class Foo
{
   ...
   private:
      int x = 0;
      int y = 0;
};

如果您有不计其数的成员,则可以创建一个POD类/结构,使用这种类型创建1个成员,然后使用最合适的初始化将其初始化为0:

class Foo
{
   ...
   private:
      struct Pod
      {
        int x,y,z,whatever;
      };
      Pod m = {0};
};

这会强制访问m.x之类的成员,...不透明

OR(可能有点hacky,但可以工作),创建一个POD结构,然后从中继承您的类。现在,您可以在默认构造函数中将memset应用于POD结构的大小

  struct Pod
  {
    Pod()
    {
       std::memset(this,0,sizeof(Pod));
    }
    int x,y,z,whatever;
  };

  class Foo : private Pod
  {
     public:
       ...
      private:
        std::string name;
        std::vector<int> elements;
  };

sizeof(Pod)值可确保memset仅将Pod的成员设置为0。

如果Pod来自无法更改的C结构,则可以在memset构造函数中移动Foo语句,并保持sizeof(Pod)

答案 1 :(得分:-1)

有人建议使用零个初始化的局部变量来编译linux内核,请参阅今年https://youtu.be/FY9SbqTO5GQ?t=742上linux.conf的演示文稿

为此,演示者团队使用了实验性的gcc开关finit-local-vars,补丁位于https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00615.html

我希望这将最终合并到gcc主分支并被广泛采用。从字面上看,我见过的每个代码样式指南都要求C / C ++编码人员在定义变量的任何地方进行明确的零赋值= 0。这是容易出错且毫无意义的猴子工作。