
Roland wrote:
Wrong. I assumed nothing about how B is packaged. To be more precise I Assume static lib (no DLL). And I am linking statically to c-runtime.
I misunderstood you, then. I thought that you meant B to be dynamic link library.
mainCRTStartup initializes the lib, and calls your main in turn.
Correct.
You may find this function in CRT sources (if you installed it together with MSVC). In multi-threaded, statically linked version of CRT this function will indirectly call TlsAlloc (or actually FlsAlloc - if present in "kernel32.dll", at least in CRT delivered with MSVC71).
I don't believe so. TlsAlloc is called from within mainCRTStartup for the main thread. (Not from DllMainCRTStartUp.)
_DllMainCRTStartup is in crtdll.c (when your DLL library is dynamically linked to CRT) or dllcrt0.c (when your DLL library is statically linked to CRT). In both files you will find _CRT_INIT, called from _DllMainCRTStartup just before user entry point (DllMain) is executed. In _CRT_INIT in dllcrt0.c you will find call to _mtinit, which is defined in tidtable.c. Here you will find "__tlsindex = FLS_ALLOC(&_freefls)". But I think that's all irrelevant in your case, as your library B (being static library) does not have an entry point.
How should this ever work? When you link the CRT statically there is no chance of even exposing DllMainCRTStartup! You may only assign _one_ entrypoint into your executable, and this is already mainCRTStartup.
Of course this will work, if you linked CRT statically to your *dynamic* library. Things are much different with static libraries, as you pointed out. In this case linker will see symbol "__tlsindex" in static runtime library that your static library is linked with (ie. indirectly in your library), and when linking your library with code of your client (ie. user of your static library) it will match it with __tlsindex in his CRT (whenever he's using static or dynamic runtime). When his mainCRTStartup (or DllMainCRTStartup) is executed, this symbol will be initialized by call to TlsAlloc (ie. inside function _mtinit). This is enough to initialize TLS index for CRT. Because this index is shared (linker did this) with static CRT your static library is linked with, effectively it will share TLS with CRT linked (statially or dynamically) with code of your client. At least this is my idea of what linker is doing, and I've confirmed that with debugger. And this is enough; execution of TlsSetValue and initialization of CRT data is delayed to first access of CRT TLS data through _getptd function (defined in tidtable.c).
Give it a try. Set a breakpoint to your entry function while statically linked. I bet you will never arrive there :-(
... and it's not required by CRT to initialize its stuff in TLS. B.