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


126

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

我了解实现上的区别,但仍不确定要使用哪个。优点/缺点是什么?

我听说过的/ MD的一个优点是,它允许某人更新运行时(例如修补安全问题),并且我的应用程序将从此更新中受益。尽管对我而言,这似乎是一个无功能:我不希望人们在不让我针对新版本进行测试的情况下更改运行时!

我有些好奇的事情:

  • 这将如何影响构建时间?(大概/ MT慢一点?)
  • 还有哪些其他含义?
  • 大多数人使用哪一个?

1
更多信息和建议,请访问:stackoverflow.com/questions/787216
Weidenrinde,2009年

Answers:


85

通过与/ MD动态链接,

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

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


10
SxS会稍微减少系统更新位。EXE声明了它想要的CRT版本(想要而不是得到-安全更新可能会否决这一要求)
MSalters

1
这是否意味着如果我使用MD进行编译并且我的程序依赖于某些dll,并且该程序在不存在依赖dll的计算机上运行,​​则该程序将失败?
gerrytan

5
@gerrytan:是的,您需要确保要运行该软件的所有计算机上都存在正在使用的适当DLL。典型的解决方案是让用户安装适当的MSVC可再发行程序包,或使用完成所有工作的安装程序。
福兹先生13年

@Royi我不确定,但是我认为/MT运行时会稍微快一点,因为您的应用程序不需要每次都搜索运行时函数的实现,我不是这个级别的专家,但是我可以肯定大多数操作系统将缓存运行时实现,因此您的应用程序将使用缓存的版本,因此差别不会那么大。请注意,我提到我不确定,因此请勿将此注释作为参数。
艾哈迈德·卡马尔

34

如果使用的是DLL,则应使用动态链接的CRT(/ MD)。

如果您为.exe和所有.dll使用动态CRT,则它们将共享一个CRT的单一实现-这意味着它们将共享一个CRT堆,并且可以在一个.exe / .dll中释放分配的内存另一个。

如果您为.exe和所有.dll使用静态CRT,则它们都将获得CRT的单独副本-这意味着它们都将使用自己的CRT堆,因此必须在与之相同的模块中释放内存已分配。您还将遭受代码膨胀(CRT的多个副本)和过多的运行时开销(每个堆从OS分配内存以跟踪其状态的开销,开销是显而易见的)。


20

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

如果使用/ MT,则可执行文件将不依赖于目标系统上存在的DLL。如果将其包装在安装程序中,则可能不会有问题,您可以选择其中一种。

我自己使用/ MT,因此可以忽略整个DLL混乱。

PS正如Fooz先生所指出的,保持一致至关重要。如果要与其他库链接,则需要使用与它们相同的选项。如果您使用的是第三方DLL,几乎可以肯定,您将需要使用运行时库的DLL版本。


14

我更喜欢与/ MT静态链接。

即使使用/ MD获得了较小的可执行文件,您仍然必须附带一堆DLL,以确保用户获得用于运行程序的正确版本。最后,与/ MT链接相比,您的安装程序将更大。

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


5
“将运行时库放入Windows目录”是一个非常糟糕的主意。您可以破坏之前做过的其他愚蠢应用程序。使用SxS并让安装程序处理它,或坚持使用/ MT。
MSalters

1
我完全同意这是一个坏主意。虽然有人这样做,所以我正在描述为什么这不是一个好主意。
阿德里安·格里戈里

@AdrianGrigore为什么具有不同库的新应用程序会导致应用程序中断?如果使用/ MD链接,您将开始加载新版本的库,对吗?
rturrado2012年

4
@rturrado:不完全是。在您的应用程序之上安装其他应用程序可能会覆盖旧版本的dll。较新的版本将不复存在。这通常称为“ dll地狱”,请参见en.wikipedia.org/wiki/DLL_Hell
Adrian Grigore 2012年

1
微软放弃了Visual Studio 2010中的WinSxS-运行时库现在可以私下部署或在system32(msdn.microsoft.com/zh-cn/library/vstudio/dd293574.aspx)中部署。
BCran

8

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

在这种情况下,您必须弄清楚如何在他们的计算机上安装正确的版本。


7

来自http://msdn.microsoft.com/zh-cn/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)链接,同时仍通过msvcrt.lib。

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


问题是“我应该使用哪个?”,这不是答案。
Leonard Inkret

1

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

如果可执行文件不使用任何人调用的lib或dll。现在的区别不是太大,因为共享方面没有发挥作用。

因此,也许您可​​以使用/ MT启动应用程序,因为没有其他令人信服的理由,但是当添加lib或dll的时间到时,可以将其更改为/ MD,而使用lib / dll则很容易。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.