Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: why does the compiler complain about uninitializxed stack variables?

47 views
Skip to first unread message

Richard Damon

unread,
Jun 19, 2022, 5:47:44 PM6/19/22
to
On 6/19/22 5:20 PM, Ron Eggler wrote:
> On Sunday, June 19, 2022 at 2:16:11 PM UTC-7, Ron Eggler wrote:
>> Hi,
>>
>> I've been wondering why the compiler (g++) complains about uninitialized stack variables unless they are explicitly initialized (even to 0). Stack variables are always initialized to 0 (unless explicitly set to another value), are they not?
>> Example:
>> void func(void) {
>> int a;
>> a +=5;
>> cout<< a <<endl;
>> }
>> yields: "warning: 'a' is used uninitialized" when a in fact is initialized to 0 implicitly, is it not?
> I in fact realized that when i declare a as static int, there is no warning.
> I actually found the following:
> It will be automatically initialized if
>
> it's a class/struct instance in which the default constructor initializes all primitive types; like MyClass instance;
> you use array initializer syntax, e.g. int a[10] = {} (all zeroed) or int a[10] = {1,2}; (all zeroed except the first two items: a[0] == 1 and a[1] == 2)
> same applies to non-aggregate classes/structs, e.g. MyClass instance = {}; (more information on this can be found here)
> it's a global/extern variable
> the variable is defined static (no matter if inside a function or in global/namespace scope) - thanks Jerry
> Never trust on a variable of a plain type (int, long, ...) being automatically initialized! It might happen in languages like C#, but not in C & C++.

THe key is that if the variables life is the full duration of the
program (due to being global or file scope of local scope but static)
then you get the default initialization to 0 if not specified. This
happens because it is generally cheap to just pre-initialize memory as
you load the program.

Local variables that are not static come into existance only when you
enter the function, and thus would need a run time operation to clear
them, which can be costly, so doesn't just happen automatically. C and
C++ try to trust the programmer.


Siri Cruise

unread,
Jun 19, 2022, 6:34:03 PM6/19/22
to
In article
<cd682469-4cc7-4399...@googlegroups.com>,
Ron Eggler <ron.e...@mistywest.com> wrote:

> > yields: "warning: 'a' is used uninitialized" when a in fact is initialized
> > to 0 implicitly, is it not?

auto variables without explicit initalisation have undefined
random, usually whatever what was at that stack word before.


> I in fact realized that when i declare a as static int, there is no warning.
> I actually found the following:
> It will be automatically initialized if

static variables without explicit initalisation are initialised
to zero, which is the OS marking those pages as zeroed.

--
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @
'I desire mercy, not sacrifice.' /|\
Discordia: not just a religion but also a parody. This post / \
I am an Andrea Chen sockpuppet. insults Islam. Mohammed

Alf P. Steinbach

unread,
Jun 20, 2022, 4:16:54 AM6/20/22
to
On 20 Jun 2022 00:33, Siri Cruise wrote:
> In article
> <cd682469-4cc7-4399...@googlegroups.com>,
> Ron Eggler <ron.e...@mistywest.com> wrote:
>
>>> yields: "warning: 'a' is used uninitialized" when a in fact is initialized
>>> to 0 implicitly, is it not?
>
> auto variables without explicit initalisation have undefined
> random, usually whatever what was at that stack word before.
>
>
>> I in fact realized that when i declare a as static int, there is no warning.
>> I actually found the following:
>> It will be automatically initialized if
>
> static variables without explicit initalisation are initialised
> to zero, which is the OS marking those pages as zeroed.

I think you forgot a weasel phrase like "usually" or "on modern desktop
systems".

Because, on a system where a pointer is not all zero bits (do they still
exist?), zero-initialization cannot logically in all cases be
implemented as an actual zeroing by the OS.

A global `void*`, say, would have to be treated much the same as a
primitive type global constant with respect to initialization.


- Alf

Siri Cruise

unread,
Jun 20, 2022, 6:05:11 AM6/20/22
to
In article <t8pad5$q0i$1...@dont-email.me>,
"Alf P. Steinbach" <alf.p.s...@gmail.com> wrote:

> On 20 Jun 2022 00:33, Siri Cruise wrote:
> > In article
> > <cd682469-4cc7-4399...@googlegroups.com>,
> > Ron Eggler <ron.e...@mistywest.com> wrote:
> >
> >>> yields: "warning: 'a' is used uninitialized" when a in fact is
> >>> initialized
> >>> to 0 implicitly, is it not?
> >
> > auto variables without explicit initalisation have undefined
> > random, usually whatever what was at that stack word before.
> >
> >
> >> I in fact realized that when i declare a as static int, there is no
> >> warning.
> >> I actually found the following:
> >> It will be automatically initialized if
> >
> > static variables without explicit initalisation are initialised
> > to zero, which is the OS marking those pages as zeroed.
>
> I think you forgot a weasel phrase like "usually" or "on modern desktop
> systems".
>
> Because, on a system where a pointer is not all zero bits (do they still
> exist?), zero-initialization cannot logically in all cases be
> implemented as an actual zeroing by the OS.

Okay. '=0' isn't that hard to type, so I initialise explicitly or
do a memset to 0. I use the boehm garbage collector which works
better if every unused variable is zeroed.

Sam Varshavchik

unread,
Jun 20, 2022, 6:37:40 AM6/20/22
to
Ron Eggler writes:

> Example:
> void func(void) {
> int a;
> a +=5;
> cout<< a <<endl;
> }
> yields: "warning: 'a' is used uninitialized" when a in fact is initialized
> to 0 implicitly, is it not?

No, it is not. Variables are not zero-initialized in every situation. This
is one of the situations where they're not.

Andreas Kempe

unread,
Aug 10, 2022, 7:41:26 PM8/10/22
to
Den 2022-06-19 skrev Ron Eggler <ron.e...@mistywest.com>:
> Hi,
>
> I've been wondering why the compiler (g++) complains about
> uninitialized stack variables unless they are explicitly initialized
> (even to 0). Stack variables are always initialized to 0 (unless
> explicitly set to another value), are they not?
> Example:
> void func(void) {
> int a;
> a +=5;
> cout<< a <<endl;
> }
> yields: "warning: 'a' is used uninitialized" when a in fact is
> initialized to 0 implicitly, is it not?

I'm a little late on the ball, but as has been stated, stack variables
are not automatically initialised on declaration. To initialise the
variable, you can either write

int a = 0;

or, in modern C++, you can also write

int a{};

Let me provide a little test program that should probably show this
being the case.

test.cpp:

#include <iostream>

void a()
{
int a = 5;
}

int b()
{
int b;
b += 2;

return b;
}

int main()
{
a();

std::cout << b() << std::endl;
}

When this program is compiled on my machine using clang without
optimisation:

clang++ -O0 test.cpp -o test

It outputs the number 7 because of the two ints ending up on the same
place in the stack.

/tmp> ./test
7

It might produce something else on your machine. Writing "int b{};" or
"int b = 0;" makes it produce the correct output of 2.

I've had cases where I'm passing structs to system calls where I've
forgotten the curly-braces after the declaration, leading to some
unexpected results when some fields get random data. This case not
being caught by the compiler since I do set some fields.

Richard Damon

unread,
Aug 10, 2022, 9:31:01 PM8/10/22
to
On 8/10/22 7:41 PM, Andreas Kempe wrote:
> Den 2022-06-19 skrev Ron Eggler <ron.e...@mistywest.com>:
>> Hi,
>>
>> I've been wondering why the compiler (g++) complains about
>> uninitialized stack variables unless they are explicitly initialized
>> (even to 0). Stack variables are always initialized to 0 (unless
>> explicitly set to another value), are they not?
>> Example:
>> void func(void) {
>> int a;
>> a +=5;
>> cout<< a <<endl;
>> }
>> yields: "warning: 'a' is used uninitialized" when a in fact is
>> initialized to 0 implicitly, is it not?
>
> I'm a little late on the ball, but as has been stated, stack variables
> are not automatically initialised on declaration. To initialise the
> variable, you can either write
>
> int a = 0;
>
> or, in modern C++, you can also write
>
> int a{};

Actually, ALL variables are "initialize" on declaration. If the object
is a class, then its constructor is run.

The problem is with the built-in types, the implicit constructor doesn't
set its value to anything (but file scope or static variables are
automatically defaut initialized). This is different that class objects,
where the "implicit" constructor is the "default" constructor.

Giving an explicit value of an explict call to the default constructor
gets you the defined value.

Alf P. Steinbach

unread,
Aug 11, 2022, 5:12:13 AM8/11/22
to
Uhm, since that's all about terminology I'd better correct it.

Default initialization for a basic type does nothing whatsoever, so
that's not the other-than-nothing that happens for static variables.

Namespace scope variables are automatically /zero-initialized/. That's
the first of three distinct phases of initialization. The following are
PHASES, the three phases are 1.1, 1.2 and 2:

1. /Static initialization/ is performed for variables with static or
thread storage duration, and consists of
1.1 /Zero-initialization/ zeroes variables. Formally it's not
performed for a variable that instead is constant-initialized.
1.2 /Constant initialization/ is where a variable is initialized
with a compile time constant initializer.
2. /Dynamic initialization/ is all other initialization, and happens
after static initialization. The standard differentiates between
unordered, partially ordered and ordered dynamic initialization.
Partially ordered is in C++17 for "an inline variable that is not an
implicitly or explicitly instantiated specialization".

In practice the values of static initialization for static storage
duration can just be part of the executable's image loaded into memory
to run the program.

Anyway, what you intended to write was probably "but static and thread
storage variables are automatically zero-initialized".

Another point: whether one imagines a do-nothing constructor, or that
simply nothing happens, is a point of view. Both views are valid, they
cannot be distinguished by effects. At least I believe so. :-o


> Giving an explicit value of an explict call to the default constructor
> gets you the defined value.

Not sure what that is intended to communicate.


- Alf

Andreas Kempe

unread,
Aug 11, 2022, 7:39:00 AM8/11/22
to
I've never really considered the fundamental types as having
constructors since they don't have other class/struct semantics, ex.
I can't inherit them. I agree with you that I don't think the
viewpoint matters for the end result.

This discussion made me realise something I hadn't realised before,
which is that I can create a simple class with a deleted default
constructor and still zero-initialise it

class num
{
public:
num() = delete;
int a;
};

int main()
{
//num my_num; // Not allowed because deleted default constructor.
num my_num{}; // Okay, initialises num::a to zero

std::cout << my_num.a << std::endl;
}

I relised this when looking at value-initialisation and coming across

9.1.2 if T has either no default constructor
([class.default.ctor]) or a default constructor that is
user-provided or deleted, then the object is default-initialized;

I learnt something new today, thank you.
0 new messages