我应该用/ MD或/ MT编译吗?

时间:2009-04-16 18:22:54

标签: c++ visual-studio msbuild msvcrt crt

在Visual Studio中,有编译标志/ MD和/ MT,可以让您选择所需的C运行时库。

我理解实现方面的差异,但我仍然不确定使用哪一个。有什么利弊?

我听说/ MD的一个优点是,这允许有人更新运行时(如可能修补安全问题),我的应用程序将从此更新中受益。虽然对我来说,这几乎看起来像一个非特征:我不希望人们改变我的运行时而不允许我测试新版本!

我很好奇的一些事情:

  • 这会如何影响构建时间? (据推测/ MT有点慢?)
  • 其他影响是什么?
  • 大多数人使用哪一个?

7 个答案:

答案 0 :(得分:75)

通过动态链接/ MD,

  • 您接触到系统更新(无论好坏),
  • 您的可执行文件可以更小(因为它没有嵌入库)和
  • 我相信至少DLL的代码段在所有正在使用它的进程之间共享(减少消耗的RAM总量)。

我还发现,在实践中,当使用静态链接的第三方二进制库(使用不同的运行时选项构建)时,主应用程序中的/ MT往往比/ MD更容易引起冲突(因为如果C运行时多次静态链接会遇到麻烦,特别是如果它们是不同版本的话)。

答案 1 :(得分:29)

如果您使用的是DLL,那么您应该选择动态链接的CRT(/ MD)。

如果你为.exe和所有.dll使用动态CRT,那么它们将共享一个CRT的实现 - 这意味着它们将共享一个CRT堆和分配在一个.exe / .dll中的内存。被另一个人释放。

如果你为.exe和所有.dll使用静态CRT,那么他们都会获得CRT的单独副本 - 这意味着他们都将使用自己的CRT堆,因此必须在同一个模块中释放内存它被分配了。您还会遇到代码膨胀(CRT的多个副本)和过多的运行时开销(每个堆从操作系统分配内存以跟踪其状态,并且开销可能很明显)。

答案 2 :(得分:18)

我相信通过Visual Studio构建的项目的默认值是/ MD。

如果使用/ MT,则可执行文件不依赖于目标系统上存在的DLL。如果你将它包装在安装程序中,它可能不会成为问题,你可以采用任何一种方式。

我自己使用/ MT,这样我就可以忽略整个DLL的混乱。

P.S。正如Mr. Fooz指出的那样,保持一致至关重要。如果您要与其他库链接,则需要使用与其相同的选项。如果您使用的是第三方DLL,则几乎可以肯定您需要使用运行时库的DLL版本。

答案 3 :(得分:14)

我更喜欢静态链接/ MT。

即使您使用/ MD获得较小的可执行文件,仍然需要发送一堆DLL以确保用户获得运行程序的正确版本。最后,与使用/ MT链接时,安装程​​序将变得更加庞大。

更糟糕的是,如果您选择将运行时库放在Windows目录中,用户迟早会安装具有不同库的新应用程序,运气不好会破坏您的应用程序。

答案 4 :(得分:8)

您将遇到/ MD的问题是CRT的目标版本可能不在您的用户计算机上(特别是如果您使用的是最新版本的Visual Studio且用户具有较旧的操作系统)。

在这种情况下,你必须弄清楚如何在他们的机器上获得正确的版本。

答案 5 :(得分:7)

来自http://msdn.microsoft.com/en-us/library/2kzt1wy3(VS.71).aspx

  

/ MT定义_MT,以便从标准头(.h)文件中选择多线程特定版本的运行时例程。此选项还会使编译器将库名称LIBCMT.lib放入.obj文件中,以便链接器将使用LIBCMT.lib来解析外部符号。创建多线程程序需要/ MT或/ MD(或其调试等价物/ MTd或/ MDd)。

     

/ MD定义_MT和_DLL,以便从标准.h文件中选择运行时例程的多线程和DLL特定版本。此选项还会使编译器将库名称MSVCRT.lib放入.obj文件中。

     

使用此选项编译的应用程序静态链接到MSVCRT.lib。该库提供了一层代码,允许链接器解析外部引用。实际工作代码包含在MSVCR71.DLL中,该代码必须在运行时提供给与MSVCRT.lib链接的应用程序。

     

当/ MD与_STATIC_CPPLIB定义(/ D_STATIC_CPPLIB)一起使用时,它将导致应用程序与静态多线程标准C ++库(libcpmt.lib)而不是动态版本(msvcprt.lib)链接,同时仍然动态链接到主CRT通过msvcrt.lib。

因此,如果我正确地解释它,那么 / MT 会动态链接, / MD 会动态链接。

答案 6 :(得分:1)

如果您正在构建使用其他dll或libs的可执行文件而不是/ MD选项是首选,因为这样所有组件将共享相同的库。当然,这个选项应该与所有涉及的模块匹配,即dll / lib / exe。

如果您的可执行文件不使用任何lib或dll而不是任何人的电话。现在差别不是很大,因为共享方面没有发挥作用。

所以也许你可以用/ MT启动应用程序,因为没有令人信服的理由,但是当它添加lib或dll的时候,你可以用lib / dll的那个将它改成/ MD这很容易。< / p>