Question

Sorry for the long post that follows.

I know that it is not a good idea to mix the statically linked and dynamically linked C and C++ runtimes supplied by Microsoft. Our application at work already mixes them unfortunately and we've been trying to fix that. For various reasons (among which unfamiliarity with MSI, the fact that we use NSIS which maybe doesn't support MSMs well, lack of time and resources) we decided to link the CRTs statically instead of dynamically. I know the reasons why this is not a good idea but it was our choice for now.


Our code is mostly standard C++ complemented by quite a lot of other open-source libraries.

The structure of the application is: various modules that result in static libraries which themselves are linked together to create various stuff among which one executable that is giving us problems.

In Release we build all our code with /MT. For some of the open-source libraries we used precompiled binaries and some of them were dlls precompiled with /MD which made us mix the runtimes. So we recompiled those ourselves with /MT and made them result in static libraries not dlls. This conversion is not done for each library, so we still link with some dlls that use /MD.


The result now is that in depends.exe all of our stuff except one executable doesn't directly depend on msvcr80.dll or msvcp80.dll. By doesn't directly depend I mean that msvcr80.dll is not a child of the root of the tree shown by depends.exe. Sometimes we do find msvcr80.dll pulled in by one of the library dlls but that's some levels deeper in the tree.

How do I find out why is msvcr80.dll on the first level for that one pesky executable? What makes that executable link directly to msvcr80.dll?

One reason could maybe be that we link statically to library A which links uses /MD so it links dynamically with the CRT. So the code in library A ends up in our executable so our executable links with msvcr80.dll. But how do I find out which one of the libraries does that?


What I tried so far:

  • load the statically linked .lib files in depends.exe -> doesn't work since depends.exe expects an executable or dll not a static library
  • use dumpbin.exe /DIRECTIVES on the statically linked .lib files -> none of them showed msvcrt80.dll (while in Debug, where we try to use /MDd for everything, they did show msvcrt80d.dll which makes me think the method is good and it proves that all the statically linked open-source libraries are compiled correctly with /MT)
  • use the /VERBOSE:LIB linker flag -> it showed that indeed it's pulling in msvcrt.lib which is the import library for msvcr80.dll so we're in trouble but it didn't say why it's doing that
  • use the /VERBOSE linker flag + in Visual Studio: Additional Dependencies libcmt.lib + Ignore all default libraries YES + Ignore specific library: msvcrt.lib in a desperate attempt to make msvcrt.lib go away or see who pulls it it. The result stumped me:
    Searching C:\Program Files\Microsoft Visual Studio 8\VC\lib\msvcrt.lib:  
      Found "public: virtual void * __thiscall type_info::`vector deleting destructor'(unsigned int)" (??_Etype_info@@UAEPAXI@Z)  
        Referenced in libcmt.lib(typinfo.obj)  
        Loaded msvcrt.lib(ti_inst.obj)  
            msvcrt.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) already defined in libcmt.lib(typinfo.obj)  
            msvcrt.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" (??4type_info@@AAEAAV0@ABV0@@Z) already defined in libcmt.lib(typinfo.obj)  
      Found "void __stdcall `eh vector destructor iterator'(void *,unsigned int,int,void (__thiscall*)(void *))" (??_M@YGXPAXIHP6EX0@Z@Z)  
        Referenced in msvcrt.lib(ti_inst.obj)
        Loaded msvcrt.lib(ehvecdtr.obj)

As far as I understand, typinfo.obj in libcmt.lib references a symbol, searches it in msvcrt.lib and after it finds in ti_inst.obj it throws an error that it's defined twice. But this doesn't make sense. If libcmt.lib already has the symbol why does it end up searching for it in msvcrt.lib and therefore bringing msvcr80.dll in my executable? And more generally, why would the static library search for symbols in the dynamic import library? Why does the linker even look at msvcrt.lib if I have it in the Ignore specific library?

Thanks for your patience :-).

Was it helpful?

Solution

I have the solution to my problem. It was a stupid mistake left there from ancient times probably.

msvcrt.lib was explicitly mentioned by us in the Additional Dependencies box :-( so of course it made the dll a dependency. And because of all the open-source libraries that box has a lot of text so we didn't notice it. And to be honest we didn't even think of looking at that box carefully since we didn't imagine there could be such a gross mistake in our projects.

OTHER TIPS

Open up your executable with depends.exe and run the profiler built into depends. I believe this will log why all your dlls are loaded, and from where they are loaded. See the "Log LoadLibrary function calls" option.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top