Say I have one executable: app.exe
I use 2 different 3rd party DLLs in this executable: foo.dll
bar.dll
and the Application must link implicitly to these DLLs, that is I cannot use ::LoadLibrary
to load them.
(Note: It's not that I cannot call LoadLibrary
, but these DLLs require static linking (C++ DLLs with __declspec(dllexport)
), so me calling LoadLibrary
doesn't make any sense because the excutable loader has already called it.)
These two DLLs do not have any dependencies on each other, that is, their load order is undefined as far as I can tell (and should be irrelevant). (Dependencies of both are basically only on the standard windows dlls (kernel32, msvcrt, etc.)
I now have the problem that I wish to control the load order of these DLLs, that is I wish that foo.dll is always loaded (DLL_PROCESS_ATTACH
) before bar.dll.
Is it somehow possible to tell the Windows DLL Loader to load one DLL before another?
Edit: To check the DLL load order of an executable, one can use the DUMPBIN.exe
utility: (Just launch the Visual Studio Command Prompt)
Edit: As per this answer / this blog entry, the NT Loader does walk the import section sequentially. (Which will result in independent DLLs being loaded in the order they appear in the import section.)
C:\path\to\program> dumpbin /IMPORTS app.exe | grep -i \.dll
MSVCR80D.dll
KERNEL32.dll
OLEAUT32.dll
MSVCP80D.dll
foo.dll
bar.DLL
This output means that MSVCR80D.dll (and its dependecies[a]) will be loaded first and that bar.DLL will be loaded last. Unload will happen in reverse order.
What I haven't found out yet is how to influence this load order ...
(Notes)
[a] : This means of course that e.g. kernel32.dll will be loaded first, because msvcr80d.dll will depend on kernel32.dll.
As per some requests, I'm adding a rationale for this: (But please, I'm still interested in this generally. I know how to work around the MFC problem.)
The Microsoft MFC DLL in it's debug version has memory leak detection built in. (As far as I can tell, it's the same mechanism used by _CrtSetDbgFlag and related tools.)
The MFC debug DLL will dump all unfreed memory when it is unloaded. Now, if you have a second DLL in your process, that is independent of MFC, and this second DLL deallocates memory on DLL_PROCESS_DETACH, the MFC reporting mechanism will report false memory leaks, if the MFC DLL is unloaded before the other dll.
If one could make sure that the debug MFC DLL is loaded first / unloaded last of all independent DLLs, then all other DLLs would already have cleaned up after themselves and MFC wouldn't report false leaks.
I have no clue why I hadn't tried this, but it seems the import section order of the resulting module does depend on the order in which the
lib
files are provided to the linker.The lib files listed here first are also first in the import section, meaning the loader will import these in order (modulo dependencies).
So, to answer that part: Just provide the lib files in the correct order to the linker.
Note: I have tried that on VS2005 and it appears to work. I don't know whether that is documented somewhere or if it changed in newer versions of VC++.
Update: While it worked back then, today I hit the case that the load order was not to be influenced by the linker command line order of the
lib
files. (Still) No clue why. (Still VS2005)I have however managed to make it work by adding the problematic DLLs to the list of delay loaded DLLs (like in Macke's answer).
Here's an idea: How about marking them as "Delay Loaded dlls" in the linker options of
app.exe
?Delay-loading will allow you to link "statically" (i.e. without LoadLibrary() et.al) but will not load the DLL and do the linking until it's actually needed.
If that is an option, then (assuming you can wait so long, i.e. do not access foo/bar dll functions before main()), you could, in main(), access a function (just fetch a function ptr or something) in
foo.dll
first, which would load it and bind all "statically" linked functions?(Maybe LoadLibrary() triggers the same link-when-needed procedure. Not sure. It would look cleaner in your code though.)
If you don't link the import library (foo.lib & bar.lib), then the loader will not automatically load the DLLs upon startup and you can call LoadLibrary() whenever you want.
On a side note, I wrote a handy little library for encapsulating loading DLLs on the fly without having to deal with LoadLibrary/GetProcAddress directly. You can read about it here.
Just add
foo.dll
to the import table ofbar.dll
, the OS loader will handle the rest.You should be able to do this without the source code for
bar.dll
, not sure if theeditbin
tool has such an option, but this is a fairly trivial edit to the PE file.You might instead be able to use the registry setting that preloads DLLs, but I wouldn't do that, you don't want
foo.dll
getting loaded into other processes that don't need it.