MSDN > Home page del forum > Visual C++ General > Linking an app in debug mode against libraries built with /MD
Formula una domandaFormula una domanda
 

Con rispostaLinking an app in debug mode against libraries built with /MD

  • venerdì 20 ottobre 2006 21.08syperk Medaglie utenteMedaglie utenteMedaglie utenteMedaglie utenteMedaglie utente
     

    Here's the situation:

    •  I have some third party DLLs, built with Visual Studio 2005, and which were compiled with the /MD switch (multithreaded DLL CRT libraries).
    •  I want to build my application in debug mode, using the debug CRT (/MDd switch), linked against the libraries above.

    In VS 2003 .NET I could get this to work, but not with VS 2005. I continually see the message "MSVCR80.DLL not found" when I try to run the app.

    The third party DLLs were built using nmake and so have external .manifest files that are in the same directory as the DLLs. The directory containing these DLLs in on the PATH.

    My app is built using the VS 2005 IDE and so has an embedded manifest.

    If I use the "depends" tool that comes with VS 2005 to look at one of the 3rd party DLLs, it shows a dependency on the correct (non-debug) CRT library, and finds that DLL in winsxs. If I use the same tool on my app, it shows a dependency on the 3rd party DLL, and then a failed sub-dependency on the non-debug CRT. Why is the OS not able to locate the correct CRT based on the manifest file for that DLL?

    Does it make any difference if the manifest is embedded in the 3rd party DLL or not?

    I've seen official statements that one shouldn't mix debug and non-debug code, but in many cases that's unavoidable. Many third party libraries are only available in their non-debug versions (built with /MD). How are we supposed to debug our programs in this case?

    Any suggestions much appreciated!

    Cheers,

    Sy

     

Risposte

  • lunedì 23 ottobre 2006 3.11syperk Medaglie utenteMedaglie utenteMedaglie utenteMedaglie utenteMedaglie utente
     Con risposta

    OK, I have the answer!

    In short: It appears that DLLs built with Visual Studio 2005 MUST have their manifests embedded in them. It is not sufficient to simply have an external manifest file in the same directory as the DLL, it must be embedded, using a command like:

    > mt.exe -manifest extlib.dll.manifest -outputresource:extlib.dll;2

    Long digression: if your DLLs were built using the visual studio IDE, then the manfests are automatically embedded, so you won't see this problem. If however, they are built using nmake makefiles, it is quite likely that the manifests will not be embedded, unless the makefile contains some jiggery-pokery like the above.

    Side note: I had earlier decided to try to build separate debug and release versions of my thrid party libraries, for use when I compile my code in debug or release mode, but quickly realized that this is almost unworkable. First, this approach means that you have two versions of each DLL floating around: one linked against the debug CRT (compiled with /MDd), and one linked againsts the non-debug CRT (compiled with /MD). The files look identical, so unless you're very organized, it's easy to get them mixed up.  Of course, you not only have the DLL, you also have the import (.lib) file associated with that DLL. Secondly you have to store the two versions in different places, and ensure that builds find the correct .lib files when building. Again, great potential for confusion. Thirdly, when you run your code, you have to ensure that the OS can find the correct versions of the DLL. The usual way to do this is to put the libraries on your PATH, but this means that you have to modify your PATH whenever you switch between debug and release builds. In theory this is all possible, but in practice it would be a nightmare.

    Out of curiosity, does anyone actually do the above?

Tutte le risposte

  • sabato 21 ottobre 2006 18.31SvenC Medaglie utenteMedaglie utenteMedaglie utenteMedaglie utenteMedaglie utente
     

    Hi Sy,

    mixing release and debug modules is mostly a problem of different C/C++ memory allocators. So if you pass around heap objects you must make sure that they are deallocated from their origin module to make sure that the correct heap is given the delete or free call.
    That would also be true for different versions of the c/c++ runtime - no matter if release or debug. So it depends on the design of the third party library if using from a different runtime is possible.
    In fact that is not the issue you are seeing above.

    I do not know if there is a "correct way" of referencing the other runtime dll, but did you try to put it in the directory of your executable, to get it in the search path?

    --
    SvenC

  • lunedì 23 ottobre 2006 1.20syperk Medaglie utenteMedaglie utenteMedaglie utenteMedaglie utenteMedaglie utente
     

    I don't think the problem is not with memory allocation issues, since the program never actually gets to run. If I link my app (compiled with /MDd) against a third party DLL (compiled with /MD), then I get a "MSVCR80.DLL not found" error as soon as the app starts.

    I did try putting the copy of MSCVR80.DLL from the redist directory of Visual Studio into the application directory, but simply changed the error to (from memroy) "an application has tried to load the C runtime in a invalid way". I also tried putting the CRT assembly directory from redist in the app directory. Again, no joy.

    I should also add that if I build my application in release mode (with /MD), then everything works fine.

    One question occurs to me: has anyone else out there managed to build a program with /MDd, and linked it against a DLL built with /MD using Visual Studio 2005? If you have, then that might suggest an answer..

  • lunedì 23 ottobre 2006 3.11syperk Medaglie utenteMedaglie utenteMedaglie utenteMedaglie utenteMedaglie utente
     Con risposta

    OK, I have the answer!

    In short: It appears that DLLs built with Visual Studio 2005 MUST have their manifests embedded in them. It is not sufficient to simply have an external manifest file in the same directory as the DLL, it must be embedded, using a command like:

    > mt.exe -manifest extlib.dll.manifest -outputresource:extlib.dll;2

    Long digression: if your DLLs were built using the visual studio IDE, then the manfests are automatically embedded, so you won't see this problem. If however, they are built using nmake makefiles, it is quite likely that the manifests will not be embedded, unless the makefile contains some jiggery-pokery like the above.

    Side note: I had earlier decided to try to build separate debug and release versions of my thrid party libraries, for use when I compile my code in debug or release mode, but quickly realized that this is almost unworkable. First, this approach means that you have two versions of each DLL floating around: one linked against the debug CRT (compiled with /MDd), and one linked againsts the non-debug CRT (compiled with /MD). The files look identical, so unless you're very organized, it's easy to get them mixed up.  Of course, you not only have the DLL, you also have the import (.lib) file associated with that DLL. Secondly you have to store the two versions in different places, and ensure that builds find the correct .lib files when building. Again, great potential for confusion. Thirdly, when you run your code, you have to ensure that the OS can find the correct versions of the DLL. The usual way to do this is to put the libraries on your PATH, but this means that you have to modify your PATH whenever you switch between debug and release builds. In theory this is all possible, but in practice it would be a nightmare.

    Out of curiosity, does anyone actually do the above?

  • lunedì 23 ottobre 2006 5.14SvenC Medaglie utenteMedaglie utenteMedaglie utenteMedaglie utenteMedaglie utente
     
     syperk wrote:

    Side note: I had earlier decided to try to build separate debug and release versions of my thrid party libraries, for use when I compile my code in debug or release mode, but quickly realized that this is almost unworkable. First, this approach means that you have two versions of each DLL floating around: one linked against the debug CRT (compiled with /MDd), and one linked againsts the non-debug CRT (compiled with /MD). The files look identical, so unless you're very organized, it's easy to get them mixed up.  Of course, you not only have the DLL, you also have the import (.lib) file associated with that DLL. Secondly you have to store the two versions in different places, and ensure that builds find the correct .lib files when building. Again, great potential for confusion. Thirdly, when you run your code, you have to ensure that the OS can find the correct versions of the DLL. The usual way to do this is to put the libraries on your PATH, but this means that you have to modify your PATH whenever you switch between debug and release builds. In theory this is all possible, but in practice it would be a nightmare.

    Out of curiosity, does anyone actually do the above?

    Microsoft does just that with its runtime and mfc

    --
    SvenC

  • martedì 24 ottobre 2006 4.08syperk Medaglie utenteMedaglie utenteMedaglie utenteMedaglie utenteMedaglie utente
     

    Just wanted to post a follow-up to my earlier mails with a couple of observations:

    • Although embedding the manifest into the DLL (as opposed to having it as an external file) fixed my "MSVCR80.DLL not found" problem, and allowed my software to startup, I haven't had any success getting my code (compiled with /MDd) to invoke functions in the DLL (compiled with /MD), even for doing relatively simple things. I wonder whether Visual Studio 2005 changes have made these libraries more incompatible than they used to be with VS 2003.
    • As a result, I've switched to compiling my debug builds using the /MD switch. If you do this, you also have to undefine the _DEBUG preprocessor macro. Otherwise you get lots of errors about _CrtDebugReportW() not found. This function is apparently inserted into your code if _DEBUG is defined, but is only defined in the debug CRT. As long as optimization is off it seems to be perfectly possible to debug programs compiled this way, and there are no concerns about CRT incompatibility.

    Cheers,

     

    Sy