I\'m having trouble with LoadLibrary() and getting an error that doesn\'t make sense to me:
::SetLastError(0);
m_hDll = ::LoadLibrary(szName);
if
The error messag means that there is an appropriate DLL found but a required procedure export is missing. Do you have the right version of the DLL?
You can use dumpbin.exe
to check what functions your DLL exports and check the spelling.
Install Debugging tools and run the gflags -i your_application.exe +sls
. After that execute application under the debugger to capture the loader traces.
Let's take this step by step:
The error message means that the dll was found but a required function is missing. (Jitter is right.) This implies that you have the dll you need, but not the right version. (Davefiddes is right, although the problem can be any dll, not just the Microsoft runtime library. And, at least for major updates, Microsoft gives its runtime libraries different names, so in that case it wouldn't be an issue.)
This doesn't make sense, because no function has been requested from the dll being loaded. (Adam is right.)
Therefore, the missing function was expected to be found not in the dll which is being explicitly loaded by the LoadLibrary command, but in a dependent dll which is being implicitly loaded at the same time, because the first dll requires it. (Zebrabox was close.)
A dependent dll is a dll that is "statically" linked to the library being explicitly loaded, via an import library, or .lib file, included on the linker step of the explicitly loaded dll. (I bet you didn't know that a "dynamic link library" could be "statically linked." Well, now you do.)
If you have multiple versions of the same dll in different folders, then this could also be a search path problem (as zebrabox suggests). Dll path search order is a complicated subject in itself: see http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx . It depends on operating system, among other things. The safest bet, where practical, is to put all the potential problem dlls in the same folder as your exe.
Dependent dlls can also have their own dependent dlls, which can make this problem very difficult to resolve. Depends might help, but if it doesn't, try filemon. The last dll that's successfully read before your error message is the one that's the wrong version.
The Microsoft gflags tool will always tell you exactly what dependency is failing to load and why.
Run gflags -i your_application.exe +sls
. After that execute the application under the debugger to capture the loader traces.
gflags is part of Debugging Tools -- you might check in C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
to see if you already have it. You can add that directory to your path, or just execute gflags from that directory in cmd.exe.
For example, after running gflags, put a break point on the ::LoadLibrary(_T("foo"))
call and step over it while looking for loader errors in your Visual Studio output window, e.g.
4b00:396c @ 479194074 - LdrpSnapThunk - ERROR: Procedure "?SetObject@vis_DollarMap@@QEAAXHPEAX@Z" could not be located in DLL "bar.dll"
First-chance exception at 0x0000000077307EF8 (ntdll.dll) in your_application.exe: 0xC0000139: Entry Point Not Found.
4b00:396c @ 479194074 - LdrpGenericExceptionFilter - ERROR: Function LdrpSnapIAT raised exception 0xc0000139
Exception record: .exr 0000000000129070
Context record: .cxr 0000000000128B80
4b00:396c @ 479194074 - LdrpHandleOneOldFormatImportDescriptor - ERROR: Snapping the imports from DLL "C:\test\64Debug\foo.DLL" to DLL "C:\test\64Debug\bar.dll" failed with status 0xc0000139
This means that during the load of foo.dll
, the dependency bar.dll
was imported, and the bar.dll
import failed.
The dependency import failed because the procedure ?SetObject@vis_DollarMap@@QEAAXHPEAX@Z
was missing -- you can demangle that to public: void __cdecl vis_DollarMap::SetObject(int,void * __ptr64) __ptr64
.
You probably have the wrong version of a dependency -- maybe you need to rebuild the dependency to get it up to date.
Run gflags -i your_application.exe -sls
afterwards to disable the loader traces.
Do you have a mismatch between the runtimes used for your app and the DLL?
A problem that's bitten me with VS 2005 in the past is that one part is built as a Release build and the other as a Debug build. These pull in different versions of the Microsoft runtime DLLs which are incompatible as you can only have one loaded in a given process.
I think the reason that you see Error 127 is because your DLL is looking for a function in the loaded runtime DLL which isn't there because it's the wrong runtime.
Two guesses from me
1. LoadLibrary calls the DllMain of the specified DLL (the first time you try and attach to your process). Long shot but is it there?
2. LoadLibrary will load the specified DLL and all it's dependencies. So if a dependant module of the DLL can't be located in the search path that will cause the load to fail - you can use depends.exe to check - available here