Intialisation order and statics

S

Spacen Jasset

Since it says in the standard that the order of initialization of
variables is indeterminate, does this also apply to a static within a
function?

e.g.

int GetInt()
{
static int test = 458;
return test;
}


when might test be initialized? Is it indeterminate like any other
object. In other words calling GetInt() before main() is executed
doesn't guarantee test has been initialized?

If this is the case how does one avoid problems with static
initialisation. For instance if I have a class A

class A
{
MyMutex mutex;
};

A a_object;

Here, let us say that MyMutex's constructor will read a static member
variable within the MyMutex class. Presumably, this is undefined
behavior since the static variable may not yet have been initialised.

If that is the case how do you avoid this sort of trap?
 
P

Peter Koch Larsen

Spacen Jasset said:
Since it says in the standard that the order of initialization of
variables is indeterminate, does this also apply to a static within a
function?

e.g.

int GetInt()
{
static int test = 458;
return test;
}


when might test be initialized? Is it indeterminate like any other object.
In other words calling GetInt() before main() is executed doesn't
guarantee test has been initialized?

Calling GetInt assures that test will be initialised, thus you'll have no
problems. In your case, test will be initialised automatically, but if you
had a more complicated element (such as a mutex), the element will be
initialised the first time you call the function.

/Peter
[snip]
 
?

=?ISO-8859-1?Q?Xavier_D=E9coret?=

Peter said:
Calling GetInt assures that test will be initialised, thus you'll have no
problems. In your case, test will be initialised automatically, but if you
had a more complicated element (such as a mutex), the element will be
initialised the first time you call the function.

which has always been a puzzle to me concerning efficiency. Does it mean
that at runtime there is a test in the function to see if the variable
is initialized? In other word, is the code:
void foo()
{
static int n = 4;
//
// ...
//
}
equivalent (once compiled) to the code:
static bool foo_run = false;
void foo()
{
static int n;
if (!foo_run) { n=4;foo_run=true; }
//
// ...
//
}

If it is the case, then using static inside function (which I thought a
good practice for it declares things closer to where it is needed) incur
a potentially huge cost!!!

Otherwise, I don't see how the generated compiled code can do without a
dynamic test?!? Oh yes, it could change the pointer function of foo so
the first time it points to the initialization of n and the second time
to a couple instructions further! Is that true?
/Peter
[snip]
 
M

msalters

Xavier Décoret wrote:

[ function statics ]
which has always been a puzzle to me concerning efficiency. Does it mean
that at runtime there is a test in the function to see if the variable
is initialized? In other word, is the code:

Probably, for complex cases.
void foo()
{
static int n = 4;
//
// ...
//
}
equivalent (once compiled) to the code:
static bool foo_run = false;
void foo()
{
static int n;
if (!foo_run) { n=4;foo_run=true; }
//
// ...
//
}

If it is the case, then using static inside function (which I thought a
good practice for it declares things closer to where it is needed) incur
a potentially huge cost!!!

Not as bad as you'd think. Modern CPUs use branch prediction, and they
tend to do quite well on such biased tests. Some compilers can even
tell the CPU that the branch is likely false, and only the first call
will be slower - but you typically don't care about that case, since
your initialization makes the function slower.
Otherwise, I don't see how the generated compiled code can do without a
dynamic test?!? Oh yes, it could change the pointer function of foo so
the first time it points to the initialization of n and the second time
to a couple instructions further! Is that true?

One of the most obvious ways is to initialize n at program startup. In
general, you can detect the ctor call if you're initializing a static
class-type object. There's no way to see the initial value of static
int n, so it may be initialized from the startup code along with the
globals.

Another way could be to use page faults on CPUs that support them.
Don't allocate RAM for the static variable, trap the page fault and
initialize the variable just-in-time (before the first read). In a
modern OS the CPU has to do this test anyway, to deal with virtual
memory.

A similar solution is to place the code (not the data) in paged-out
memory, and use the same trap to initialize the variable on the first
call of the funtion.

Regards,
Michiel Salters
 
S

Spacen Jasset

Peter said:
"Spacen Jasset" <[email protected]> skrev i en meddelelse ....
Calling GetInt assures that test will be initialised, thus you'll have no
problems. In your case, test will be initialised automatically, but if you
had a more complicated element (such as a mutex), the element will be
initialised the first time you call the function.

/Peter
[snip]


I see that. But what if GetInt() istself is called before main() starts
to run. I.e. by something like this:


int myint = GetInt();

could test be uninitiaised at this point. In most cases it will be since
the linker will most likly put myint in an initialised data segment.
However, that isn't possible for a class object since it's constructor
must be called. I don't see anything explicit in the standard that says
static variables inside always get initialised when they are called.
 
M

msalters

Spacen Jasset wrote:
....
I see that. But what if GetInt() istself is called before main() starts
to run. I.e. by something like this:


int myint = GetInt();

could test be uninitiaised at this point. In most cases it will be since
the linker will most likly put myint in an initialised data segment.
However, that isn't possible for a class object since it's constructor
must be called. I don't see anything explicit in the standard that says
static variables inside always get initialised when they are called.

6.7/4 states that
"A local object of POD type (3.9) with static storage duration
initialized
with constant-expressions is initialized before its block is first
entered."
( that covers your example of a static int )

"An implementation is permitted to perform early initialization of
other
local objects with static storage duration under the same conditions
that
an implementation is permitted to statically initialize an object with
static storage duration in namespace scope (3.6.2). Otherwise such an
object is initialized the first time control passes through its
declaration; such an object is considered initialized upon the
completion
of its initialization."

which covers the more interesting cases of static objects with
constructors that can be observed.

HTH,
Michiel Salters
 
S

Spacen Jasset

msalters said:
Spacen Jasset wrote:
...



6.7/4 states that
"A local object of POD type (3.9) with static storage duration
initialized
with constant-expressions is initialized before its block is first
entered."
( that covers your example of a static int )

"An implementation is permitted to perform early initialization of
other
local objects with static storage duration under the same conditions
that
an implementation is permitted to statically initialize an object with
static storage duration in namespace scope (3.6.2). Otherwise such an
object is initialized the first time control passes through its
declaration; such an object is considered initialized upon the
completion
of its initialization."

which covers the more interesting cases of static objects with
constructors that can be observed.

HTH,
Michiel Salters


That's interesting, thanks. The the following is also correct?:


class A
{
public:
GetInt()
{
return myInt;
}
private:
static int myInt;
};


you can't be sure myInt is initialised when GetInt() is called, but you
can if you use a local static variable.

Therefore were have:
Singletons should always be initialised as local static objects within a
funcion to gurantee proper initialisation.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top