I just added a C Windows DLL project to a Visual Studio (2022) solution. The wizard put a DllMain
in there. That jumped out at me; I didn't remember my other DLLs having DllMain
functions;
Searching my code, it turns out that none of my 9 DLLs have DllMain functions. Yet they all build and work fine. I checked the project settings for all of these projects:
- None of them have the linker
/NOENTRY
option set. - They all have
/SUBSYSTEM:WINDOWS
set. - None of them have the linker
/NODEFAULTLIB
option set - They are certainly all DLLS.
So I commented out that DllMain in the new project I just added. It still built just fine.
My knowledge is clearly out of date. I thought a DllMain
used to be required. I remember years ago getting linker errors in my DLLs when I failed to add a DllMain
.
So my questions are:
- Why do my DLLs not require DllMain? Is there some build setting I did not check?
- Is there any downside to not having one?
(Note that these DLLS all export C classes. None of them are resource DLLs. All have been working fine for 6 years. Some of them use thread-local storage. Some of them have static variables inside of functions. I always thought that using things like these necessitated a DllMain)
CodePudding user response:
The runtime library ("CRT" = C/C Runtime Library) provides the real DLL entry point _DllMainCRTStartup
, that does things like initializing global variables before calling your DllMain
. There's documentation on MSDN that describes this:
Documentation of the linker /ENTRY
option is also relevant:
There's also a library-provided weak symbol for your DllMain
, so the call from the real entrypoint to DllMain
doesn't fail at link time with an unresolved external. From the first document above:
By default, if you do not provide a
DllMain
function, Visual Studio provides one for you and links it in so that_DllMainCRTStartup
always has something to call.
The things you mentioned like thread-local storage do require using the library-provided entrypoint; they'll break if you use the /ENTRY
option to link.exe to replace the library entrypoint with your own or /NOENTRY
to disable it. None of them require anything to be done by the DllMain
that the library entrypoint calls.