We recently faced this linkage error:
error LNK2005: _DllMain@12 already defined in MSVCRT.lib(dllmain.obj)
Searching gives ~36K results as of July 2012, many of which seem high quality (StackOverflow, MS, CodeProject etc.), and I was certain it would be a simple matter of finding a fix online and blindly applying it. However it seems the root cause in our particular case wasn’t covered yet (AFAIK), and it seems worthwhile to document.
The MS KB article teaches that this is a linkage order problem – MFC libs must be linked before the CRT ones – but none of the fixes the article proposes worked. We did have one build configuration which was successful and one which failed with the above LNK2005 (Release – but it really doesn’t matter) so I dumped two /VERBOSE linker outputs for the two configurations and diffed them. After some admittedly tedious inspection, an interesting difference came up – these lines were dumped only in the successful build:
Found __afxForceUSRDLL
…
Referenced in Stdafx.obj
Loaded mfcs100d.lib(dllmodul.obj)
The symbol name implies that it is intended to force some linkage, and including it seems to have the beneficial effect of loading the mfc lib mfcs100d.lib. Indeed, searching reveals the following lines in dllmodul.cpp:
#ifdef _X86_ extern "C" { int _afxForceUSRDLL; } #else extern "C" { int __afxForceUSRDLL; } #endif
and the following in afx.h:
// force inclusion of DLLMODUL.OBJ for _USRDLL #ifdef _USRDLL #pragma comment(linker, "/include:__afxForceUSRDLL") #endif
So it turns out there’s a single condition that governs the linkage to the MFC library mfcs100/d (the one containing DllModul.obj, which exports _afxForceUSRDLL), and that condition is – _USRDLL being defined. Our linking project was indeed a dll and somehow the default _USRDLL preprocessor macro was missing from it – restoring the definition fixed the linkage.
So bottom line, if you get a ‘DllMain@12 already defined’ linkage error for a dll, here’s another thing to try: make sure _USRDLL is defined in your project C++ property sheets.
Filed under: Debugging, MFC