4
votes

Quotes:

From the document "Best Practices for Creating DLLs" http://download.microsoft.com/download/a/f/7/af7777e5-7dcd-4800-8a0a-b18336565f5b/DLL_bestprac.doc of Microsoft:

"DLLs often have complex interdependencies that implicitly define the order in which they must be loaded. The library loader efficiently analyzes these dependencies, calculates the correct load order, and loads the DLLs in that order."[1]

"(within DLLMain) Use the memory management function from the dynamic C Run- Time (CRT). If the CRT DLL is not initialized, calls to these functions can cause the process to crash."[2]

From MSDN: http://msdn.microsoft.com/en-us/library/988ye33t.aspx

"The _DllMainCRTStartup function does several things, including calling _CRT_INIT, which initializes the C/C++ run-time library and invokes C++ constructors on static, non-local variables. Without this function, the run- time library would be left in an uninitialized state."[3]

"In addition to initializing the C run-time library, _DllMainCRTStartup calls a function called DllMain."[4]

Questions:

If your DLL depends on CRT DLLs, based on [1], CRT DLLs will be loaded first (be initialized first), so how [2] could happen ?

Based on [3] and [4], _DllMainCRTStartup will calls _CRT_INIT which initializes the CRT, so how [2] could happen ?

If an executeable file loads your DLL by "Implicit linking", the _DllMainCRTStartup (and DLLMain) of your DLL will be called before the entry point (mainCRTStartup or WinMainCRTStartup) of the executeable file, based on [3] - _DllMainCRTStartup calls _CRT_INIT which initializes the CRT, and the mainCRTStartup is going to initialize the CRT too, so what actually happend with the CRT ?

If your DLL will be loaded before mainCRTStartup, the calling to CRT functions within DLLMain or other export functions is safe or not ?

Who will initialize CRT DLLs actually ?

1

1 Answers

10
votes

You are working from the assumption that the entrypoint for a DLL is always _DllMainCRTStartup. This is not the case, it is merely the linker's default. It can be anything a programmer wants it to be, swiftly and easily changed with the linker's /ENTRYPOINT option. There is nothing that Microsoft can do to prevent this. Not a very good practice, pointing that out is was the point of that document.

So the [2] mishap is easily invoked if such a custom entrypoint doesn't also ensure to initialize the CRT explicitly. Which doesn't just involve initializing the CRT runtime state, it also involves initializing global state of the DLL, like calling C initializers, the constructors of static C++ objects and allocating thread-local variables. Something the DLL version of the CRT cannot do. Keep in mind that _DllMainCRTStartup and _CRT_INIT are linked into the DLL itself, that code is not in the DLL version of the CRT.

The dynamic CRT's own runtime state is initialized by the CRT DLL's own entrypoint, the Windows loader ensures it runs first.