前段时间编译一个引用自己写的静态库的程序时老是出现链接时的多个重定义的错误,而自己的代码明明没有重定义这些东西,譬如:
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,并选择运行时库的发布版本或调试版本。

选项 说明
/MD 定义 _MT 和 _DLL 以便同时从标准 .h 文件中选择运行时例程的多线程特定版本和 DLL 特定版本。此选项还使编译器将库名 MSVCRT.lib 放入 .obj 文件中。用此选项编译的应用程序静态链接到 MSVCRT.lib。该库提供允许链接器解析外部引用的代码层。实际工作代码包含在 MSVCR71.DLL 中,该库必须在运行时对于与 MSVCRT.lib 链接的应用程序可用。当 在定义了 _STATIC_CPPLIB (/D_STATIC_CPPLIB) 的情况下使用 /MD 时,它将导致应用程序通过静态多线程标准 C++ 库 (libcpmt.lib) 而非动态版本 (msvcprt.lib) 进行链接,同时仍通过 msvcrt.lib 动态链接到主 CRT。
/MDd 定义 _DEBUG、_MT 和 _DLL,以便从标准 .h 文件中选择运行时例程的调试多线程特定版本和 DLL 特定版本。它还使编译器将库名 MSVCRTD.lib 放入 .obj 文件中。
/ML 使编译器将库名 LIBC.lib 放入 .obj 文件中,以便链接器使用 LIBC.lib 解析外部符号。这是编译器的默认操作。LIBC.lib 不提供多线程支持。
/MLd 定义 _DEBUG 并使编译器将库名 LIBCD.lib 放入 .obj 文件中,以便链接器使用 LIBCD.lib 解析外部符号。LIBCD.lib 不提供多线程支持。
/MT 定义 _MT, 以便从标准头 (.h) 文件中选择运行时例程的多线程特定版本。此选项还使编译器将库名 LIBCMT.lib 放入 .obj 文件中,以便链接器使用 LIBCMT.lib 解析外部符号。创建多线程程序需要 /MT 或 /MD(或它们的调试等效选项 /MTd 或 /MDd)。
/MTd 定义 _DEBUG 和 _MT。定义 _MT 会导致从标准 .h 文件中选择运行时例程的多线程特定版本。此选项还使编译器将库名 LIBCMTD.lib 放入 .obj 文件中,以便链接器使用 LIBCMTD.lib 解析外部符号。创建多线程程序需要 /MTd 或 /MDd(或它们的非调试等效选项 /MT 或 MD)。
/LD 创建 DLL。将 /DLL 选项传递到链接器。链接器查找 DllMain 函数,但并不需要该函数。如果没有编写 DllMain 函数,链接器将插入返回 TRUE 的 DllMain 函数。链接 DLL 启动代码。如果命令行上未指定导出 (.exp) 文件,则创建导入库 (.lib);将导入库链接到调用您的 DLL 的应用程序。将 /Fe 解释为命名 DLL 而不是 .exe 文件;默认程序名成为基名称.dll 而不是基名称.exe。如果还未显式指定 /M 选项之一,则将默认运行时库支持更改为 /MT。
/LDd 创建调试 DLL。定义 _DEBUG。

警告 不要混合使用运行时库的静态版本和动态版本。在一个进程中有多个运行时库副本会导致问题,因为副本中的静态数据不与其他副本共享。链接器禁止在 .exe 文件内部既使用静态版本又使用动态版本链接,但您仍可以使用运行时库的两个(或更多)副本。例如,当与用动态 (DLL) 版本的运行时库链接的 .exe 文件一起使用时,用静态(非 DLL)版本的运行时库链接的动态链接库可能导致问题。(还应该避免在一个进程中混合使用这些库的调试版本和非调试版本)。

Visual C++ 编译器选项 /MD、/ML、/MT、/LD相关推荐

  1. Visual C++ 编译器选项

    Visual   C++   编译器选项               选项   作用       /O1   创建小代码       /O2   创建快速代码       /Oa   假设没有别名   ...

  2. msdn关于Visual C++ 编译器选项的说明

    msdn关于Visual C++ 编译器选项的说明: 这些选项选择单线程或多线程运行时例程,指示多线程模块是否为 DLL,并选择运行时库的发布版本或调试版本. 选项 说明 /MD 定义 _MT 和 _ ...

  3. VC调试选项说明:md /mdd /ml /mt/mtd

    VC调试选项说明:md /mdd /ml /mt/mtd 1. VC编译选项 多线程                             (/MT) 多线程调试                   ...

  4. /MD, /MDD, /ML, /MT,/MTD(使用运行时库)

    1. VC编译选项 多线程(/MT) 多线程调试(/MTd) 多线程 DLL (/MD) 多线程调试 DLL (/MDd) 2. C 运行时库                              ...

  5. md /mdd /ml /mt/mtd

    From: http://www.cnblogs.com/eddyshn/archive/2009/11/23/1608823.html VC编译选项 多线程(/MT) 多线程调试(/MTd) 多线程 ...

  6. /MD, /MDD, /ML, /MT,/MTD(使用运行时库) .

    1. VC编译选项 多线程(/MT) 多线程调试(/MTd) 多线程 DLL (/MD) 多线程调试 DLL (/MDd) 2. C 运行时库                              ...

  7. /MD 与 /MT、/MTD与/MDD的区别

    VS在 属性页的 C/C++ -> Code Generation -> Runtime Library 一项中总共有四个选项 /MD 与 /MT./MTD与/MDD,它们分别有什么区别? ...

  8. VS 编译时 /MD 与 /MT、/MTD与/MDD的区别

    VS在 属性页的 C/C++ -> Code Generation -> Runtime Library 一项中总共有四个选项 /MD 与 /MT./MTD与/MDD,它们分别有什么区别? ...

  9. vs MD /MDD /ML /MT /MTD的简单介绍

    1.MD /MDD /ML /MT /MTD的简单介绍 在编译ATL工程后,生成的dll在本电脑上能用,在别人的电脑上不能用.通过Depends工具分析一下,原来是编译选项没有选对,别的电脑上没有我生 ...

最新文章

  1. mac 安装Pillow
  2. 斯坦福马超:随机梯度下降,也爱躺「平」……why?
  3. 小孩子如何学会语言?科学家使用计算机模型解释儿童语言学习过程
  4. mac 终端里进入mysql和退出
  5. kaggle的kernel-only比赛中出现Your Notebook cannot use internet access in this competition解决方案
  6. mysql 交换工资_LeetCode:627.交换工资
  7. Linux下的lua和boost c++的搭建和安装
  8. 为什么川渝的超市要求顾客必须“要有妈”?
  9. python3.8+mysql+pymysql安装
  10. mysql和php长度的漏洞_mysql和php字符长度判断
  11. 利用iframe来做无刷新上传
  12. stm32F407 + FreeRTOS + FAT 文件系统移植
  13. 分享PHP多功能在线工具箱网站源码,安装教程详解
  14. KVM/QEMU(virt-manager)使用iso镜像安装macOS bigsur 11.4
  15. SpringBoot Web开发
  16. IBM SPSS statistics v28.0安装教程
  17. OpenMP Sections
  18. 手撸spring源码分析IOC实现原理
  19. 腾讯云IM回调接口-单聊发言后回调
  20. 第1-7课:基础开胃菜

热门文章

  1. c语言蓝牙接收6,终于搞定了通过两路蓝牙接收数据
  2. ubuntu 在线安装php,ubuntu在线安装LNMP
  3. html启动word程序,Word工具栏直接启动外部程序
  4. c++经典编程题_【经典C语言知识】C/C++编程难点总结
  5. C# 读取根目录的json文件中的某个值
  6. matlab不同调制方式下性能比较,用不同调制方式实现跳/扩频混合通信的抗干扰性能...
  7. Android入门(14)| 通知
  8. leetcode253. 会议室 II
  9. 理解Caffe的网络模型
  10. 《机器学习实战》笔记(04):基于概率论的分类方法 - 朴素贝叶斯分类