强制本地变量默认初始化

Forcing local variables to be default-initialized

本文关键字:默认 初始化 变量      更新时间:2023-10-16

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

有没有办法强制编译器自动初始化所有的局部变量?也许是内置了此功能的编译器,或者是通用编译器(如GCC或Clang)的编译器开关?我可以接受Gnu扩展;它不一定是标准的。

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

我厌倦了将所有本地int和私有类字段分配给0。

我所知道的没有开关可以做,即使它确实存在,它也只是一个"调试"功能,不能在生产代码中使用。

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

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

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

依赖一个未在标准中定义为/的开关会使代码不可移植。在某个时刻,有人会使用您的代码在其他平台上进行交叉编译,但这将失败。

作为一种帮助/保护,像Coverity这样的一些工具(注意:我不隶属于这家公司)可以检测代码中未初始化的POD成员。可能也有免费的工具可以做同样的事情。

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

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

如果你有无数个成员,也许可以创建一个POD类/结构,创建一个具有这种类型的成员,并使用最有效的初始化方法将其初始化为0:

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

这迫使访问m.x等成员。。。不透明

或者(可能有点麻烦,但有效),创建一个POD结构,然后从中继承您的类。您现在可以在默认构造函数中对POD结构的大小应用memset

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结构,则可以在Foo构造函数中移动memset语句,保持sizeof(Pod)

有一个建议是用零初始化的本地变量编译linux内核,请参阅今年linux.conf的演示https://youtu.be/FY9SbqTO5GQ?t=742

为了实现这一点,演示者团队使用了一个实验性的gcc开关finit-local-vars,这里有补丁https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00615.html

我希望这将最终合并到gcc主分支并被广泛采用。实际上,我看到的每一个代码风格指南都要求C/C++程序员在定义变量的任何地方进行显式零赋值= 0。这是一项容易出错且毫无意义的猴子工作。

EDIT 2022:在GCC 12 中添加了一个开关-ftrivial-auto-var-init