# Correctness of constructors before main()

This topic is 3660 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi there. In C++, it's possible to statically declare objects whose constructors get called before main(), std::cin and std::cout for example. Trouble for me is, this doesn't work across objects which aren't defined in the same file. For example, the following is unsafe
Foo::Foo() {
std::cout << "Hi\n";
}
Foo foo;
Foo bar;

int main () {
return 0;
}


This will work only if the linker happens to decide that std::cout's constructor is called before foo's or bar's. AFAIK, this behaviour is undefined (although we can guarantee that foo will be constructed before bar). This is causing me problems because I'm hiding initialisation code in anonymous constructors like this. It's elegant when it works. I don't expect it to be possible to guarantee the order of construction outside of main() (in fact, I can think of good reasons not to allow that), but can anyone tell me if guarantees can be made for the initial values of built-in types? If you have
const char * text = "Hello.";
int main() {


there isnt a constructor for "text" which copies in "Hello" from elsewhere, it's part of the compiled binary and loaded into memory before the program starts, right? Can I be sure that if instead of creating "Foo foo;" outside of main() and finding it undefined, I can write "Foo*foo=0;" and that will definitely be assigned its value before any of my extramain constructors are called? Thank you and good night.

##### Share on other sites
The solution I would suggest is to avoid global objects as much as possible. I know the standard did it, but if it could be redone, I bet it would be done differently.

Particularly what you need to avoid is if you have a global object whose constructor or destructor depends on another global object. If you start doing this, seriously, it's time for redesign.

In your case, just put Foo foo, and Bar bar in main and pass it along to other functions which use them.

##### Share on other sites
If you want to guarantee that std::cout will be initialized before creating your Foo objects, you can create a std::basic_ios<char>::Init object in your source file before the Foo objects are created. Ex:
std::basic_ios<char>::Init init;Foo foo;Foo bar;

Objects with static storage duration are guaranteed to be zero initialized before all other initialization happens.

##### Share on other sites
Quote:
 Original post by SiCraneObjects with static storage duration are guaranteed to be zero initialized before all other initialization happens.

Really? What about my const char * text = "Hello" example? When does that cease to be zero?

##### Share on other sites
Sometime after zero initialization occurs and before dynamic initialization occurs.

##### Share on other sites
However, the comment in MingW's iostream header says:

Quote:
 /** * @name Standard Stream Objects * * The header declares the eight standard stream * objects. For other declarations, see * http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#10 and the * @link s27_2_iosfwd I/O forward declarations @endlink * * They are required by default to cooperate with the global C library's * @c FILE streams, and to be available during program startup and * termination. For more information, see the HOWTO linked to above. */

This suggests that there are techniques to guarantee something global is available before other things, and that the implementations are required to employ them so that it is safe to use cout as you do.

##### Share on other sites
Quote:
Original post by visitor
However, the comment in MingW's iostream header says:

Quote:
 /** * @name Standard Stream Objects * * The header declares the eight standard stream * objects. For other declarations, see * http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#10 and the * @link s27_2_iosfwd I/O forward declarations @endlink * * They are required by default to cooperate with the global C library's * @c FILE streams, and to be available during program startup and * termination. For more information, see the HOWTO linked to above. */

This suggests that there are techniques to guarantee something global is available before other things, and that the implementations are required to employ them so that it is safe to use cout as you do.

It's possible there are non-standard mechanisms, but I'm not aware of any standard ones. In general, I would avoid the non-standard mechanism, since there's a better workaround anyway.

##### Share on other sites
If the standard requires that cout and cin are available to be used at program start-up what does it matter if the compiler writers use a non-standard technique to achieve this?

In particular the <iostream> header contains the following line, just as SiCrane suggested:
// For construction of filebuffers for cout, cin, cerr, clog et. al.static ios_base::Init __ioinit;

As <iostream> will be included before your code it will work.

##### Share on other sites
Quote:
 Original post by visitorIf the standard requires that cout and cin are available to be used at program start-up what does it matter if the compiler writers use a non-standard technique to achieve this?In particular the header contains the following line, just as SiCrane suggested:// For construction of filebuffers for cout, cin, cerr, clog et. al.static ios_base::Init __ioinit;As will be included before your code it will work.

I definitely remember seeing it fail before, but that definitely was years ago and I no longer remember the circumstances. Perhaps it's what you're saying, that iostream wasn't included first, which caused the problem. Even so, why not just avoid the hassle by avoiding globals? [smile]

1. 1
2. 2
3. 3
Rutin
23
4. 4
5. 5
khawk
14

• 9
• 11
• 11
• 23
• 12
• ### Forum Statistics

• Total Topics
633653
• Total Posts
3013164
×