简体   繁体   中英

LoadLibrary seemingly loading wrong DLL

I'm having a strange problem with LoadLibrary on Windows. First some background. This application depends on Qt, and Qt is split into several libraries. I am trying to upgrade versions of Qt, but without breaking anyone. The newer Qt library is backwards compatible with the old one. That means that an application built with the older version can run if it loads the newer version. The opposite is not true -- an application built with the newer version will have missing symbols if the older one is loaded.

The Qt DLLs are in version specific directories (say c:\\qt\\qt-4.5.2\\lib and c:\\qt\\qt-4.8.1\\lib as examples). There is also a common directory that most developers have in their PATH that contains the "current" version of all the third party libraries we use (call it c:\\common\\lib ). This is where the Qt libraries would normally be found when running an application.

I put the new Qt version libraries in the common location, and everything seemed to be working OK, except for one case. The application in question is split into multiple libraries, some of which are loaded by calling LoadLibrary() . Some of these runtime loaded DLLs depend on Qt libraries. In one case, the loaded DLL depends on QtXml , which itself depends on QtCore .

Here's where it gets weird. An application depends on QtCore and also loads a library that depends on QtXml . The application and library were built linking with the old version of Qt. If this application is run with just the common directory in the PATH, everything works because the new Qt version DLLs are loaded from the common directory. However, if the PATH contains the directory where the old Qt version DLLs are stored before the common directory, then loading the runtime DLL fails with missing symbols.

(This situation arises when doing automated unit testing, with scripts explicitly setting the PATH to use the specific library version.)

As near as I can figure, the application is loading the old version of QtCore.dll and the runtime loaded DLL is (somehow) loading the new version of QtXml.dll , which fails because the already loaded QtCore doesn't have the symbols it needs.

But this seems impossible, since the PATH is something like c:\\qt\\qt-4.5.2\\lib;c:\\common\\lib (plus other unrelated paths). If I remove the newer QtXml from the common lib directory (not replace it with the old version, just remove it), then LoadLibrary() succeeds, because it loads the 4.5.2 version of all the Qt libraries. But that's not a good long term solution, since running without the Qt specific version directory in the PATH (common) will fail to find QtXml .

How could this be? How could LoadLibrary() (or whatever it calls recursively to resolve the library's dependencies) load a library from later in the PATH ? I cannot find anything that would indicate that the common library directory is given special consideration (it's not a set DLL directory). It's not mentioned in the build process, it's just something developers have in their PATH for convenience.

btw, a similar situation exists on Linux with LD_LIBRARY_PATH and dlopen() , and it works just fine there. This is something Windows is doing differently that I don't understand. Does anyone have any insight into what could be going wrong?

LoadLibrary has lots of surprising behaviors. Make sure you fully grok all of the Remarks for it in MSDN.

If there's already a library loaded (any version) with the same name, LoadLibrary just returns a handle to the already-loaded DLL. That may be coming into play in your scenario.

Next, if you've specified a relative path or just a file name, LoadLibrary applies arcane search rules . Your PATH variable is typically the last place to search . It's likely that some other rule is finding the "wrong" DLL before it even gets to checking the PATH. A good guideline is to always use an absolute path the file you want to load to be sure that its search rules don't grab the wrong file. A common security flaw is to not control where LoadLibrary searches, and an attacker convinces your application to load a doctored DLL.

And, finally, it's possible for an installer to apply DLL redirection that can override what you ask for and where it might be found. I'm not sure if this is common for Qt DLLs or not, but you might want to check your registry.

I've occasionally used ProcMon from SysInternals to observe a program while it's loading DLLs. You can see each place it checks, which may give you a clue as to why it's finding the wrong version.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM