vs的运行库 MT MTd MD MDd区别

49 篇文章 2 订阅
23 篇文章 2 订阅

MT: mutithread  Static,多线程库,编译器会从运行时库里面选择多线程静态连接库来解释程序中的代码,即连接LIBCMT.lib库

MTd:mutithread debug Static ,多线程调试版,连接LIBMITD.lib库

MD:mutithread  +Dynamic,多线程动态库,连接MSVCRT.lib库,这是个导入库,对应动态库为MSVCRT.dll

MDd: mutithread +Dynamic+debug,多线程动态调试库,连接MSVCRTD.lib库,对应动态库为MSVCRTD.dll

具体见:

选项         

说明

/MD

使应用程序使用运行库的多线程并特定于 DLL 的版本。 定义 _MT 和 _DLL,并使编译器将库名 MSVCRT.lib 放入 .obj 文件中。

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

/MDd

定义 _DEBUG_MT 和 _DLL,并使应用程序使用运行库的调试多线程并特定于 DLL 的版本。 它还使编译器将库名 MSVCRTD.lib 放入 .obj 文件中。

/MT

使应用程序使用运行库的多线程静态版本。 定义 _MT 并使编译器将库名 LIBCMT.lib 放入 .obj 文件中,以便链接器使用 LIBCMT.lib 解析外部符号。

/MTd

定义 _DEBUG 和 _MT。 此选项还使编译器将库名 LIBCMTD.lib 放入 .obj 文件中,以便链接器使用 LIBCMTD.lib 解析外部符号。

/LD

创建 DLL。

将 /DLL 选项传递到链接器。 链接器查找 DllMain 函数,但并不需要该函数。 如果没有编写 DllMain 函数,链接器将插入返回 TRUE 的 DllMain 函数。

链接 DLL 启动代码。

如果命令行上未指定导出 (.exp) 文件,则创建导入库 (.lib);将导入库链接到调用您的 DLL 的应用程序。

将 /Fe(命名 EXE 文件) 解释为命名 DLL 而不是 .exe 文件;默认程序名成为基名称.dll 而不是基名称.exe。

除非显式指定 /MD,否则将暗指 /MT

/LDd

创建调试 DLL。 定义 _MT 和 _DEBUG

vs 工具上修改地方是:“项目 -> C/C++ ->代码生成 -> 运行库 

1.以小写“d”结尾的选项表示的DEBUG版本的,没有“d”的为RELEASE版本。大型项目中必须要求所有组件和第三方库的运行时库是统一的,否则将会出现LNK2005井喷。

2.多线程调试和多线程DLL调试的区别是动态链接还是静态链接C运行时库(C runtime Library, CRT)。

如果是动态链接(MD/MDd),你的程序就依赖C运行时的动态链接库(比如VS2010的msvr100.dll),当你的程序在其他没有这个dll的电脑上运行就会出现错误(找不到这个dll)。

如果是静态链接(MT/MTD),C运行库直接链接到你的程序里,你的程序就不依赖C运行时库的dll了。

微软是推荐是用动态链接的,因为这种链接方式可以减少可执行文件的大小、可以减少内存的使用、避免链接问题。

 /MT和/MTd

  /MT和/MTd表示采用多线程CRT库的静态lib版本。该选项会在编译时将运行时库以静态lib的形式完全嵌入。该选项生成的可执行文件运行时不需要运行时库dll的参加,会获得轻微的性能提升,但最终生成的二进制代码因链入庞大的运行时库实现而变得非常臃肿。当某项目以静态链接库的形式嵌入到多个项目,则可能造成运行时库的内存管理有多份。(即会有多个堆,容易使释放内存出现问题)。

容易出现关于__acrt_first_block == header异常,根本的原因是对象在析构时不正确的释放内存导致的。见:c++:动态库接口函数返回stl对象的设计原则塈‘__acrt_first_block == header’异常原因分析_10km的专栏-CSDN博客

  /MD和/MDd

  /MD和/MDd表示采用多线程CRT库的动态dll版本,会使应用程序使用运行时库特定版本的多线程DLL。链接时将按照传统VC链接dll的方式将运行时库MSVCRxx.DLL的导入库MSVCRT.lib链接。当多项目以MD方式运作时,其内部会采用同一个堆

 结论:/MD和/MDd将是潮流所趋,/ML和/MLd方式请及时放弃,/MT和/MTd在非必要时最好也不要采用了

这是个很典型的问题,在MSDN上也有描述。问题是这样的:

在一个DLL里面分配内存,然后在DLL的调用者EXE那里释放内存。

当DLL和EXE里面有一个是使用MT连接CRT的时候就有问题。如果DLL和EXE都使用MD,那么就没有问题。

解决办法:

1.exe和dll 都使用MDd运行库。

2.在dll中封装一个模板类,使模板类实现。

3.在dll中使用虚函数,目的就是是创建和删除都是使用同一个crt. 如果我们创建2个虚函数,一个用来分配内存,一个用来释放内存。在对象构造的时候,这个对象的虚表里面就已经指向了创建这个对象的模块里面的CRT的new和delete,那么当我们在DLL里面调用虚函数来释放的时候,系统会为我们找到构造对象时候的释放函数。这样就没有问题了。

见代码

class MyWrapperEx
{
public:
    explicit MyWrapperEx(int* p) : m_p(p)
    {}

    virtual ~MyWrapperEx()
    {
        if (m_p)
        {
            delete m_p;
            m_p = nullptr;
        }
    }
    virtual void ChangeValue(int isize)
    {
        int* p = new int[isize];
        if (m_p)
        {
            delete m_p;
            m_p = p;
        }
    }
private:
    int* m_p;
};

void funcWrapperdll(MyWrapperEx& p)
{
    p.ChangeValue(2);
}

class MyWrapperEx;
int main()
{
    MyWrapperEx w2(new int);
    funcWrapperdll(w2);

}

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值