(转帖) Visual C++ 编译器选项 /MD、/ML、/MT、/LD 收藏
前段时间编译一个引用自己写的静态库的程序时老是出现链接时的多个重定义的错误,而自己的代码明明没有重定义这些东西,譬如: LIBCMT.lib(_file.obj) : error LNK2005: ___initstdio already defined in libc.lib(_file.obj) LIBCMT.lib(_file.obj) : error LNK2005: ___endstdio already defined in libc.lib(_file.obj) LIBCMT.lib(_file.obj) : error LNK2005: __cflush already defined in libc.lib(_file.obj) LIBCMT.lib(_file.obj) : error LNK2005: __iob already defined in libc.lib(_file.obj) LIBCMT.lib(osfinfo.obj) : error LNK2005: __alloc_osfhnd already defined in libc.lib(osfinfo.obj) LIBCMT.lib(osfinfo.obj) : error LNK2005: __set_osfhnd already defined in libc.lib(osfinfo.obj) LIBCMT.lib(osfinfo.obj) : error LNK2005: __free_osfhnd already defined in libc.lib(osfinfo.obj) LIBCMT.lib(osfinfo.obj) : error LNK2005: __get_osfhandle already defined in libc.lib(osfinfo.obj) LIBCMT.lib(osfinfo.obj) : error LNK2005: __open_osfhandle already defined in libc.lib(osfinfo.obj) LIBCMT.lib(tolower.obj) : error LNK2005: __tolower already defined in libc.lib(tolower.obj) LIBCMT.lib(tolower.obj) : error LNK2005: _tolower already defined in libc.lib(tolower.obj) 等等。 所以初步估计是编译器的问题,通过网上搜索和查看msdn,原来是Visual C++ 编译器选项的关于单线程或多线程运行时例程的问题:我的那个静态库编译时/ML单线程版本的,而引用它的程序是/MT多线程版本的,他们在编译分别讲libc.lib和LIBCMT.lib连接到各自的代码中,估计libc.lib和LIBCMT.lib只是单线程与多线程的区别,基本代码相差无几,所以会产生链接时重定义错误;然后把编译静态库的选项/ML改成/MT就没事了。 要注意的是:/MD也是多线程版本的;被应用的用户链接库要和应用者有相同的编译选项,/MD与/MT一起有时候会有错误的,有时候就没有,我试过这种情况;而/MD和/ML似乎是没有问题的;/MT和/ML是肯定会有问题的。有没有其他情况就不清楚了,有兴趣的可以测试一下,^_^ 如果是代码是用于多线程的,最好编译成多线程版本的,否则可能会出现一些意想不到的问题。 编译器选项设置(vc6):工程 -> 设置 -> C/C++ -> 工程选项 里可以修改 附: 下面是msdn关于Visual C++ 编译器选项的说明: 这些选项选择单线程或多线程运行时例程,指示多线程模块是否为 DLL,并选择运行时库的发布版本或调试版本。 选项 说明 当在定义了 _STATIC_CPPLIB (/D_STATIC_CPPLIB) 的情况下使用 /MD 时,它将导致应用程序通过静态多线程标准 C++ 库 (libcpmt.lib) 而非动态版本 (msvcprt.lib) 进行链接,同时仍通过 msvcrt.lib 动态链接到主 CRT。 链接 DLL 启动代码。 如果命令行上未指定导出 (.exp) 文件,则创建导入库 (.lib);将导入库链接到调用您的 DLL 的应用程序。 将 /Fe 解释为命名 DLL 而不是 .exe 文件;默认程序名成为基名称.dll 而不是基名称.exe。 如果还未显式指定 /M 选项之一,则将默认运行时库支持更改为 /MT。 警告 不要混合使用运行时库的静态版本和动态版本。在一个进程中有多个运行时库副本会导致问题,因为副本中的静态数据不与其他副本共享。链接器禁止在 .exe 文件内部既使用静态版本又使用动态版本链接,但您仍可以使用运行时库的两个(或更多)副本。例如,当与用动态 (DLL) 版本的运行时库链接的 .exe 文件一起使用时,用静态(非 DLL)版本的运行时库链接的动态链接库可能导致问题。(还应该避免在一个进程中混合使用这些库的调试版本和非调试版本)。 知识库文章 Q140584 也讨论如何选择适当的 C 运行时库。 有关 DLL 的进一步讨论,请参见 DLL。 在 Visual Studio 开发环境中设置此编译器选项 打开此项目的“属性页”对话框。有关详细信息,请参见设置 Visual C++ 项目属性。 请参见 RuntimeLibrary 属性。
关于cl编译选项ML,MT,MD的解释 此三选项意为指定链接的C-Runtime Library. ML : 单线程静态库 LIBC.lib |