在 Visual Studio 中,有编译标志/MD 和/MT,它们允许您选择所需的 C 运行时库类型。
我明白在实现上的区别,但是我仍然不确定使用哪一个。优缺点是什么?
我听说/MD 的一个优点是,它允许用户更新运行时(比如修补安全问题) ,我的应用程序将从这次更新中受益。尽管对我来说,这似乎是一个非特性: 我不希望人们改变我的运行时,而不允许我对新版本进行测试!
有些事情我很好奇:
我相信通过 VisualStudio 构建的项目的默认值是/MD。
如果使用/MT,则可执行文件将不依赖于目标系统上存在的 DLL。如果你在安装程序中包装这个,这可能不会是一个问题,你可以选择任何一种方式。
我自己使用/MT,这样我就可以忽略整个 DLL 混乱。
附言。正如 福兹先生指出的那样,保持一致至关重要。如果要链接其他库,则需要使用与它们相同的选项。如果使用第三方 DLL,那么几乎可以肯定需要使用运行时库的 DLL 版本。
来自 http://msdn.microsoft.com/en-us/library/2kzt1wy3(VS.71).aspx:
/MT Definition _ MT,以便从标准头(。H)档案。此选项还使编译器将库名称 LIBCMT.lib 放入。Obj 文件,以便链接器使用 LIBCMT.lib 解析外部符号。创建多线程程序需要/MT 或/MD (或它们的调试等价物/MTd 或/MDd)。 /MD 定义 _ MT 和 _ DLL,以便从标准中选择特定于多线程和 DLL 的运行时例程版本。H 档案。此选项还会导致编译器将库名称 MSVCRT.lib 放入。Obj 文件。 使用此选项编译的应用程序静态链接到 MSVCRT.lib。此库提供了一层代码,允许链接器解析外部引用。实际的工作代码包含在 MSVCR71.DLL 中,它必须在运行时对与 MSVCRT.lib 链接的应用程序可用。 当/MD 与定义的 _ STATIC _ CPPLIB (/D _ STATIC _ CPPLIB)一起使用时,它将导致应用程序链接到静态多线程标准 C + + 库(libcpmt.lib)而不是动态版本(msvcprt.lib) ,同时仍然通过 msvcrt.lib 动态链接到主 CRT。
/MT Definition _ MT,以便从标准头(。H)档案。此选项还使编译器将库名称 LIBCMT.lib 放入。Obj 文件,以便链接器使用 LIBCMT.lib 解析外部符号。创建多线程程序需要/MT 或/MD (或它们的调试等价物/MTd 或/MDd)。
/MD 定义 _ MT 和 _ DLL,以便从标准中选择特定于多线程和 DLL 的运行时例程版本。H 档案。此选项还会导致编译器将库名称 MSVCRT.lib 放入。Obj 文件。
使用此选项编译的应用程序静态链接到 MSVCRT.lib。此库提供了一层代码,允许链接器解析外部引用。实际的工作代码包含在 MSVCR71.DLL 中,它必须在运行时对与 MSVCRT.lib 链接的应用程序可用。
当/MD 与定义的 _ STATIC _ CPPLIB (/D _ STATIC _ CPPLIB)一起使用时,它将导致应用程序链接到静态多线程标准 C + + 库(libcpmt.lib)而不是动态版本(msvcprt.lib) ,同时仍然通过 msvcrt.lib 动态链接到主 CRT。
因此,如果我正确地解释它,然后 /MT静态链接和 海事处动态链接。
通过动态链接/MD,
我还发现,在实践中,当使用使用不同运行时选项构建的静态链接的第三方二进制库时,主应用程序中的/MT 往往比/MD 更容易引起冲突(因为如果 C 运行时是静态链接的多次,特别是如果它们是不同的版本,你就会遇到麻烦)。
我更喜欢静态链接/MT。
即使您使用/MD 获得了一个较小的可执行文件,您仍然需要提供大量的 DLL,以确保用户获得正确的版本来运行您的程序。最后,您的安装程序将比链接/MT 时更大。
更糟糕的是,如果您选择将运行时库放在 windows 目录中,用户迟早会安装一个具有不同库的新应用程序,如果运气不好,就会破坏您的应用程序。
使用/MD 时会遇到的问题是,CRT 的目标版本可能不在用户机器上(特别是如果您使用的是最新版本的 Visual Studio,而用户使用的是较旧的操作系统)。
在这种情况下,您必须弄清楚如何将正确的版本放到他们的机器上。
如果您使用的是 DLL,那么您应该使用动态链接的 CRT (/MD)。
如果将动态 CRT 用于。还有前妻什么的。Dlls 然后它们将共享 CRT 的单个实现-这意味着它们将共享一个单独的 CRT 堆和分配在一个堆中的内存。Exe/.Dll 可以在另一个中释放。
如果您使用静态 CRT。还有前妻什么的。Dlls 会得到 CRT 的一个独立副本,这意味着它们都使用自己的 CRT 堆,因此内存必须在分配它的同一个模块中释放。您还会遇到代码膨胀(CRT 的多个副本)和额外的运行时开销(每个堆从操作系统分配内存以跟踪其状态,这些开销可能是显而易见的)。
如果您正在构建使用其他 dlls 或 libs 的可执行文件,则首选/MD 选项,因为这样所有组件将共享相同的库。当然,这个选项应该匹配所有涉及的模块,即 dll/lib/exe。
如果您的可执行文件不使用任何 lib 或 dll 而不使用任何人的调用。现在差别不是很大,因为共享方面没有发挥作用。
因此,也许你可以使用/MT 来启动应用程序,因为没有其他令人信服的理由,但是当它需要添加一个 lib 或 dll 时,你可以使用 lib/dll 来将它改为/MD,这很容易。