8

At some point I remember reading that threads can't be safely created until the first line of main(), because compilers insert special code to make threading work that runs during static initialization time. So if you have a global object that creates a thread on construction, your program may crash. But now I can't find the original article, and I'm curious how strong a restriction this is -- is it strictly true by the standard? Is it true on most compilers? Will it remain true in C++0x? Is it possible for a standards conforming compiler to make static initialization itself multithreaded? (e.g. detecting that two global objects don't touch one another, and initializing them on separate threads to accelerate program startup)

Edit: To clarify, I'm trying to at least get a feel for whether implementations really differ significantly in this respect, or if it's something that's pseudo-standard. For example, technically the standard allows for shuffling the layout of members that belong to different access specifiers (public/protected/etc.). But no compiler I know of actually does this.

Joseph Garvin
  • 18,725
  • 17
  • 83
  • 150
  • "is it strictly true by the standard" - the C++03 standard has nothing to say on the subject of threads. Places to look as far as current behaviour is concerned would be POSIX (which is of course *a* standard, just not *the* standard), MSDN, Boost, or other implementation-specific docs for the compiler, platform and threading API you use. – Steve Jessop Sep 18 '09 at 15:25

3 Answers3

6

What you're talking about isn't strictly in the language but in the C Run Time Library (CRT).
For a start, if you create a thread using a native call such as CreateThread() on windows then you can do it anywhere you'd like because it goes straight to the OS with no intervention of the CRT.
The other option you usually have is to use _beginthread() which is part of the CRT. There are some advantages to using _beginthread() such as having a thread-safe errno. Read more about this here. If you're going to create threads using _beginthread() there could be some issues because the initializations needed for _beginthread() might not be in place.

This touches on a more general issue of what exactly happens before main() and in what order. Basically you have the program's entry point function which takes care of everything that needs to happen before main() with Visual Studio you can actually look at this piece of code which is in the CRT and find out for yourself what exactly's going on there. The easyest way to get to that code is to stop a breakpoint in your code and look at the stack frames before main()

shoosh
  • 70,450
  • 50
  • 199
  • 310
  • Thanks, this gives me some idea of what the situation is like on Windows with MSVC. I'm still curious about other platforms though, and it doesn't really answer whether it's safe on Windows or not (does _beginthread() actually rely on any initialization that may not have taken place yet?). – Joseph Garvin Sep 18 '09 at 18:22
  • I wish I knew this as well. The docs doesn't seem to mention it. – shoosh Sep 18 '09 at 19:40
2

The underlying problem is a Windows restriction on what you can and cannot do in DllMain. In particular, you're not supposed to create threads in DllMain. Static initialization often happens from DllMain. Then it follows logically that you can't create threads during static initialization.

MSalters
  • 159,923
  • 8
  • 140
  • 320
  • 1
    But note: `During process startup and DLL initialization routines, new threads can be created, but they do not begin execution until DLL initialization is done for the process` from http://msdn.microsoft.com/en-us/library/ms682453%28v=VS.85%29.aspx – Martin York Jul 16 '11 at 21:29
  • Fair point, hadn't seen that. Note that the comment applies specifically to `CreateThread` though, `_beginthreadex` does not have this exception. – MSalters Jul 18 '11 at 08:01
0

As far as I can tell from reading the C++0x/1x draft, starting a thread prior to main() is fine, but still subject to the normal pitfalls of static initialization. A conforming implementation will have to make sure the code to intialize threading executes before any static or thread constructors do.

coppro
  • 13,900
  • 3
  • 54
  • 73