Monday, March 24, 2008

Use /MT[d] or /MD[d]?

Visual Studio 2005 C++ introduces new /MT[d] and /MD[d] compiler options.

The single-threaded CRT (libc.lib, libcd.lib) (formerly the /ML or /MLd options) are no longer available. Instead, multithreaded CRT has been added.


/MD

causes application to use the multithread- and DLL-specific version of the run-time library. Applications compiled with this option are linked to MSVCRT.lib. This library provides a layer of code that allows the linker to resolve external references. The actual working code is contained in MSVCR80.DLL, which must be available at run time to applications linked with MSVCRT.lib.

/MT

causes your application to use the multithread, static version of the run-time library. Defines _MT and causes the compiler to place the library name LIBCMT.lib into the .obj file so that the linker will use LIBCMT.lib to resolve external symbols.


I would like draw you attention that the default runtime library settings for newly generated projects has been changed. Static Library (.lib) as well Dynamic Library(.dll) and Application projects are always generated as a Multi-threaded Debug DLL (/MDd) and Multi-threaded DLL (/MD) for Debug and Release configurations correspondingly.

Static Library

Debug

Release

VisualStudio 2003 Single-threaded Debug (/MLd)Single-threaded (/ML)
VisualStudio 2005Multi-threaded Debug DLL (/MDd)Multi-threaded DLL (/MD)

Dynamic Library

Debug

Release

VisualStudio 2003 Multi-threaded Debug (/MTd) Multi-threaded (/MT)
VisualStudio 2005Multi-threaded Debug DLL (/MDd)Multi-threaded DLL (/MD)

Application

Debug

Release

VisualStudio 2003 Single-threaded Debug (/MLd)Single-threaded (/ML)
VisualStudio 2005Multi-threaded Debug DLL (/MDd)Multi-threaded DLL (/MD)


As I understand it the difference between these two build options is how dlls and executables interact with each other. /MT is probably usable only with for Static Libraries (and only for that dlls which do not exchange heap placed variables). There is a problem when you passing heap placed variable from application to dll and use it (dereference) if projects are built with compiler option different from /MD[d].

Microsoft is pointing to the potential error when passing CRT objects across DLL boundaries. /MT is making project staticaly linked with LIBCMT.lib, so in fact two project built with /MT compiler option will use separate copies of CRT. Each copy of the CRT library has a separate and distinct state. As such, CRT objects such as file handles, environment variables, and locales are only valid for the copy of the CRT where these objects are allocated or set. When a DLL and its users use different copies of the CRT library, you cannot pass these CRT objects across the DLL boundary and expect them to be picked up correctly on the other side. Also, because each copy of the CRT library has its own heap manager, allocating memory in one CRT library and passing the pointer across a DLL boundary to be freed by a different copy of the CRT library is a potential cause for heap corruption.

Example


This example passes a file handle across a DLL boundary.
The DLL and .exe file are built with /MD, so they share a single copy of the CRT.
If you rebuild with /MT so that they use separate copies of the CRT, running the resulting test1Main.exe results in an access violation.

Dynamic Library
// test1Dll.cpp
// compile with: /MD /LD
#include <stdio.h>
__declspec(dllexport) void writeFile(FILE *stream)
{
char s[] = "this is a stringn";
fprintf( stream, "%s", s );
fclose( stream );
}

Application
// test1Main.cpp
// compile with: /MD test1dll.lib
#include <stdio.h>
#include <process.h>
void writeFile(FILE *stream);

int main(void)
{
FILE * stream;
errno_t err = fopen_s( &stream, "fprintf.out", "w" );
writeFile(stream);
system( "type fprintf.out" );
}


References:


/MD, /MT, /LD (Use Run-Time Library) - http://msdn2.microsoft.com/en-us/library/2kzt1wy3.aspx
Potential Errors Passing CRT Objects Across DLL Boundaries - http://msdn2.microsoft.com/en-us/library/ms235460(VS.80).aspx
C Run-Time Libraries - http://msdn2.microsoft.com/en-us/library/abx4dbyh(VS.80).aspx

2 comments:

Tina said...

Keep up the good work.

Anonymous said...

Thanks for the explanation. I was trying to find a good explanations for the different runtime choices.