Reputation: 1015
In C++, plain-old-data (POD) local variables are uninitialized by default. I've noticed, though, that this leads to bugs, since attempting to read the value of an uninitialized variable is undefined behavior.
Is there a way to force the compiler to automatically initialize all local variables? Perhaps a compiler that has this feature built in, or a compiler switch for one of the common compilers, like GCC or Clang? I would be fine with a Gnu extension; it doesn't have to be standard.
I would expect the variables to be default-initialized, meaning that an int
would be set to 0.
I am bored with assigning all local int
s and private class fields to 0.
Upvotes: 2
Views: 3663
Reputation: 1015
There is a proposal to compile linux kernel with zero initialized local variables, see the presentation from linux.conf this year https://youtu.be/FY9SbqTO5GQ?t=742
To accomplish this the presenter team used an experimental gcc switch finit-local-vars
, patch is here https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00615.html
I hope this will be eventually merged to gcc main branch and adopted widely. Literally every code style guide I've seen demanded C/C++ coders to make an explicit zero assignment = 0
wherever they defined a variable. This is error prone and meaningless monkey work.
EDIT 2022: A switch -ftrivial-auto-var-init
was added to GCC 12
Upvotes: 0
Reputation: 140168
There is no switch to do that I know about, and even if it did exist, it would be only a "debug" feature, not to be used in production code.
Example: Electric fence library has an option to initialize memory to 0 or 0xff
EF_FILL When set to a value between 0 and 255, every byte of allocated memory is initialized to that value. This can help detect reads of uninitialized memory. When set to -1, some memory is filled with zeroes (the operating system default on most systems) and some memory will retain the values written to it during its last use.
(only works for allocated memory, not automatic memory).
Relying on a switch that isn't defined as/in a standard would make your code non-portable. At some point, someone will use your code to cross compile it on other platforms and that will fail.
As a help/safeguard, some tools like Coverity (note: I'm not affiliated with this company) can detect uninitialized POD members in your code. There may be free tools that do the same.
So what I would do in cases of one or 2 POD members (c++11):
class Foo
{
...
private:
int x = 0;
int y = 0;
};
If you have a zillion members, maybe create a POD class/struct, create 1 member with this type and initialize it to 0 using whatever initialization works best:
class Foo
{
...
private:
struct Pod
{
int x,y,z,whatever;
};
Pod m = {0};
};
That forces to access members like m.x
, ... not transparent
OR (maybe slightly hacky but works), create a POD structure, then inherit your class from it. You can now apply memset
on the size of the POD structure in the default constructor
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;
};
The sizeof(Pod)
value ensures that memset
only sets the members of Pod
to 0.
If Pod
comes from a C structure that you cannot change, you can move the memset
statement in Foo
constructor, keeping sizeof(Pod)
Upvotes: 1