473,729 Members | 2,177 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

The "static initialization order fiasco" and constants

Hi,

I had a problem in my code recently which turned out to be the 'the "static
initialization order fiasco"' problem
(<http://www.parashift.c om/c++-faq-lite/ctors.html#faq-10.12>)

The FAQ section describes a solution using methods returning references to
static objects.

But consider:

Maths.h:

namespace Maths
{
const double Pi = 3.1415926535897 9323846;

const double DegreesToRadian s = Pi / 180.0;
const double RadiansToDegree s = 1.0 / DegreesToRadian s;

const double RadiansToThousa ndthsOfMinutes = 180.0 / Pi * 60.0 * 1000.0;

const double FeetToMetres = 0.3048;
const double MetresToFeet = 1.0 / FeetToMetres;
}
Foo.cpp:

namespace Foo
{
const double x = Bar::TwoPi();
}

Bar.h:

namespace Bar
{
double TwoPi()
}

Bar.cpp:

namespace Bar
{
double TwoPi()
{
return Maths.Pi * 2.0;
}
}
(My actual problem was slightly more complex than this, but this is
My problem arose because Maths::Pi had not been initialised before Foo::x,
Foo::x was equal to zero. Probably lucky to be zero at all, could have been
anything I guess?

The FAQ way to solve this would be to change the constants to functions?

I don't want to change them to macros, but the thought of having to change
these into functions just seems... I dunno... overkill just for the sake of
several constants? (Especially when quite a lot of code uses these
constants, and up until now I think we've been *extremely* lucky!)

Are functions my best way out of this predicament?

The thought occurs that members of numeric_limit<c lasses are faced with
the same problem? Is there still the danger here that using numeric_limit<>
static members might not be initialized themselves when used to initialize
other static data?

Any advice appreciated.

--
Regards,
Steve

Apr 20 '07 #1
3 5855
Steve Folly wrote:
I had a problem in my code recently which turned out to be the 'the
"static initialization order fiasco"' problem
(<http://www.parashift.c om/c++-faq-lite/ctors.html#faq-10.12>)

The FAQ section describes a solution using methods returning
references to static objects.

But consider:

Maths.h:

namespace Maths
{
const double Pi = 3.1415926535897 9323846;

const double DegreesToRadian s = Pi / 180.0;
const double RadiansToDegree s = 1.0 / DegreesToRadian s;

const double RadiansToThousa ndthsOfMinutes = 180.0 / Pi * 60.0 *
1000.0;

const double FeetToMetres = 0.3048;
const double MetresToFeet = 1.0 / FeetToMetres;
}
Foo.cpp:
An #include is probably missing..
>
namespace Foo
{
const double x = Bar::TwoPi();
}

Bar.h:

namespace Bar
{
double TwoPi()
;
}

Bar.cpp:
Another missing #include here...
>
namespace Bar
{
double TwoPi()
{
return Maths.Pi * 2.0;
}
}
(My actual problem was slightly more complex than this, but this is
.... an unfinished sentence?
>

My problem arose because Maths::Pi had not been initialised before
Foo::x, Foo::x was equal to zero. Probably lucky to be zero at all,
could have been anything I guess?
No, zero it should have been.
The FAQ way to solve this would be to change the constants to
functions?
Most likely. For example, the 'Math.Pi' should actually be a function

namespace Math {
double Pi() { return 3.14159...; }
}
I don't want to change them to macros, but the thought of having to
change these into functions just seems... I dunno... overkill just
for the sake of several constants? (Especially when quite a lot of
code uses these constants, and up until now I think we've been
*extremely* lucky!)

Are functions my best way out of this predicament?
Sure.
The thought occurs that members of numeric_limit<c lasses are faced
with the same problem? Is there still the danger here that using
numeric_limit<s tatic members might not be initialized themselves
when used to initialize other static data?
Actually, the compiler is allowed to do magic tricks to ensure that any
of objects from the library are initialised in the proper order (like
'std::cout', for example), so library are not subject to static object
initialisation fiasco. We as users are not so lucky.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 20 '07 #2
On 20/4/07 19:46, in article f0**********@ne ws.datemas.de, "Victor Bazarov"
<v.********@com Acast.netwrote:
>Foo.cpp:

An #include is probably missing..
Yep, sorry, was in a hurry to post!
>(My actual problem was slightly more complex than this, but this is

... an unfinished sentence?
.... "My actual problem was slightly more complex than this, but this is a
cut down minimal example." (So minimal it's even missing the #includes!)
namespace Math {
double Pi() { return 3.14159...; }
}
That'd be 'Maths' - I'm in the UK... ;-)
>Are functions my best way out of this predicament?

Sure.
I suppose if I 'inline' them an optimizing compiler could optimize away the
overhead of the function call? (We use Visual Studio 2005; I'll investigate
this).
Actually, the compiler is allowed to do magic tricks to ensure that any
of objects from the library are initialised in the proper order (like
'std::cout', for example), so library are not subject to static object
initialisation fiasco. We as users are not so lucky.
Boo! Not fair!
Very helpful. Thanks for your prompt reply Victor.

--
Regards,
Steve

"...which means he created the heaven and the earth... in the DARK! How good
is that?"

Apr 20 '07 #3
On Apr 20, 8:32 pm, Steve Folly <moderatedn...@ spfweb.co.ukwro te:
I had a problem in my code recently which turned out to be the
'the "static initialization order fiasco"' problem
(<http://www.parashift.c om/c++-faq-lite/ctors.html#faq-10.12>)
That problem normally only affects types with non-trivial
constructors. Static initialization is guaranteed to take place
before dynamic.
The FAQ section describes a solution using methods returning
references to static objects.
But consider:
Maths.h:
namespace Maths
{
const double Pi = 3.1415926535897 9323846;
No problem: static initializatino.
const double DegreesToRadian s = Pi / 180.0;
The problem here is the "variable" Pi. Basically, the
standard requires initialization with constant expressions
to occur before any dynamic initialization. It then defines
integral constant expressions (which allow for "const
variables and static data members of integral or enumeration
types initialized wuith constant expressions"); it then goes
on to define other constant expressions (which can only be
used for the purpose of non-local static object
initialization) , amongst which arithmetic constant
experssions: according to the standard (§5.19/3):

An arithmetic constant expression shall satisfy the
requirements for an integral constant expression, except
that

-- floating literals need not be cast to integral or
enumeration type, and

-- conversions to floating point types are permitted.

Note that your expressions do not qualify, because they
contain a const variable which is *not* of integral or
enumeration type.

This looks like an oversight to me. If:

const double DegreesToRadian s = 3.1415926535897 9323846 / 180.0;

requires static initialization, I don't see why your
expression shouldn't. (Historically, of course, C didn't
allow the use of const variables in this context.) On the
other hand... the precision used in floating point
arithmetic like the above is not specified---all that is
guaranteed is that it is at least as much as a double.
Whereas when you assign to a variable, the precision is
guaranteed to be exactly that of the type of the variable.
So that allowing const variables would require that a cross
compiler emulate exactly the floating point of the target
machine; the above, however, only requires some floating
point of as much or greater precision.
const double RadiansToDegree s = 1.0 / DegreesToRadian s;
const double RadiansToThousa ndthsOfMinutes = 180.0 / Pi * 60.0 * 1000.0;
const double FeetToMetres = 0.3048;
const double MetresToFeet = 1.0 / FeetToMetres;
}
The same comments applies to the other constants, of course.

[...]
My problem arose because Maths::Pi had not been initialised before Foo::x,
Foo::x was equal to zero. Probably lucky to be zero at all, could have been
anything I guess?
No. Objects with static lifetime are guaranteed to be
initialized with 0 (converted to the proper type).
The FAQ way to solve this would be to change the constants to functions?
That's the classical solution.
I don't want to change them to macros, but the thought of having to change
these into functions just seems... I dunno... overkill just for the sake of
several constants? (Especially when quite a lot of code uses these
constants, and up until now I think we've been *extremely* lucky!)
I doubt that there's really much difference between an
inline function and a const variable defined in another
translation unit.
Are functions my best way out of this predicament?
Probably. Inline functions will also optimize better, since
the compiler will be able to see the actual value in all of
the translation units.

Otherwise, you could define the values as macros (using only
floating point literals and other macros) in the compilation
unit which defines the variables, something along the lines
of:

namespace Maths
{
#define PI 3.1415926535897 9323846
const double Pi = PI ;
#define DEGREES_TO_RADI ANS PI / 180.0
const double DegreesToRadian s = DEGREES_TO_RADI ANS ;
// ...
}

Since the macros wouldn't be in a header, the namespace
polution is limited.
The thought occurs that members of numeric_limit<c lasses are faced with
the same problem?
Are they? If you look at them carefully, you'll see that
the "constants" which are not necessarily of integral type
(i.e. whose type depends on the instantiation) are in fact
functions. Probably for this very reason. (Although
frankly, a good implementation could arrange for the values
to be expressed as literals. I think it's more a means of
allowing an exact bit pattern to be specified for floating
point values. Something along the lines of:

template<>
double
numeric_limits< double >::max()
{
static unsigned char r[] = { 0x7F, 0xEF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF } ;
return *reinterpret_ca st< double* >( r ) ;
}

This was probably felt to be more reliable than trying to
express it as a decimal literal with type double.)
Is there still the danger here that using numeric_limit<>
static members might not be initialized themselves when used to initialize
other static data?
No. Since the non-functions all have integral type.

--
James Kanze (Gabi Software) email: ja*********@gma il.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 20 '07 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

23
5679
by: ian justice | last post by:
Before i post actual code, as i need a speedyish reply. Can i first ask if anyone knows off the top of their head, if there is a likely obvious cause to the following problem. For the moment i've reduced my form request to a simple text string entry, instead of my desired optional parameters. As i have been stuck with a single unfathomable glitch for over a year. Basically, if i enter queries such as ; "select * from table" "select * from...
14
3217
by: lawrence | last post by:
To call I would do something like: $headline = McSelectJustOneField::callDatastore("cbHeadline"); Is this the correct use of the static keyword, to implement a Singleton design?
3
12366
by: Ajax Chelsea | last post by:
can not the "static const int" be replaced by "static enum" anywhere? is it necessary that define special initialization syntax for "static const int"?
4
1536
by: Pat | last post by:
I would like to know what is the meaning of : static vector<int> v; What is the difference with: vector<int> v;
9
2308
by: Neil Kiser | last post by:
I'm trying to understand what defining a class as 'static' does for me. Here's an example, because maybe I am thinking about this all wrong: My app will allows the user to control the fonts that the app uses. So I will need to change the fonts depending on what settings the user has entered. However, it seems kind of wasteful to me to go to teh registry, fetch the font information and create new font objects for every form that I am...
11
2154
by: comp.lang.php | last post by:
function blah($item) { if (!isset($baseDir)) { static $baseDir = ''; $baseDir = $item; print_r("baseDir = $baseDir\n"); } $dirID = opendir($item); while (($fyl = readdir($dirID)) !== false) { if (is_dir("$baseDir/$fyl")) blah($item);
16
10528
by: John Kelsey | last post by:
Back in the "old" days with C, I used to do something like... struct { char Description; float price; } Items = { {"Apple", 1.99}, {"Banana", 2.04}
5
8864
by: none | last post by:
I'd like to create a new static property in a class "hiding" the property present in a base class. Since this needs to happen at runtime I tried doing this via DynamicMethod. But obviously the created methods are not "registered" and only available through the DynamicMethod class. So a method lookup finds the origin property. A little test: public class DerivedClass : BaseClass {
14
6020
by: Jess | last post by:
Hello, I learned that there are five kinds of static objects, namely 1. global objects 2. object defined in namespace scope 3. object declared static instead classes 4. objects declared static inside functions (i.e. local static objects) 5. objects declared at file scope.
0
8913
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8761
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9426
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9280
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9142
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6722
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6016
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
2
2677
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2162
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.