MSVC Debug 与 Release 库

代码:https://gitee.com/Kyle12/StudyProject/tree/master/cmake/lib_debug_release

CMake Debug后缀

set_target_properties(liba PROPERTIES DEBUG_POSTFIX "d")
或者
set(CMAKE_DEBUG_POSTFIX "d")
这样生成的库或者exe程序名会多一个d字符。如下

链接 vc++ 运行时库

通过/MD、/MT 可以改变MSVC运行库,

  • /MD代表使用动态运行时库,程序运行时需要有MSVCRversionnumber.DLL,这些库是通过安装Download Microsoft Visual C++ Redistributables 获得。例如msvcp140.dll就是在 Microsoft Visual C++ Redistributable for Visual Studio 2015中。
  • /MT会使用静态运行时库,MSVC库会编译链接到exe程序中,所以系统不安装VC++库也可以正常运行,但是这会增加exe的大小,且由于不能共享使用公用的DLL也会消耗更多内存。
  • /MD、/MT都有对应的debug版,/MDd、/MTd,链接时使用的库也是对应的Debug版,例如msvcp140d.dll则是VC++ 2015的Debug版库。这种库需要安装Visual studio 20xx时才能获得,非开发设备一般都没有这种库。

Debug库和Release库

MSVC中需要区分Debug库和Release库,因为Debug和Release模式下STL的实现不一样。例如 x64架构下std::vector和std::string的sizeof大小,Debug模式下为32和40,而Release模式下为24和32。之所以不一样是因为Debug模式下会存储额外的调试信息。

因为C++ STL对象Debug库和Release模式下大小不一致,所以链接库的时候需要注意库是Debug版还是Release版本,需要根据当前程序是Debug还是Release版本选择对应的库版本。

MSVC 链接动态库

 对于动态库都有对应的DLL,DLL本身就是可以执行文件,系统可以直接读取并执行,其内部已经包含了所有运行时的函数和符号。所以动态库生成后其已经可以与编译环境分离,也就是说如果你编译了一个动态库,这个库也不会受编译器版本的限制,大部分情况下不同VS版本都可以通用。

如果动态库的API没使用C++ STL对象,或者所有的API使用C语言接口,此时在使用库时可以不用区分Debug版本还是Releas版本,Debug版可以直接使用Release版本的库。这也是为什么很多库使用C++编写,却提供C语言的接口。

如果使用了使用C++ STL对象,需要严格按照Debug版使用Debug版本的库,Release版本使用Release版本的库,否则程序可以链接成功,但是运行时会报内存错误,而且这个错误很难被察觉。

MSVC 链接静态库

静态库只是一个中间编译状态,并不能直接运行,还需要与调用者编译链接才能运行。使用库时需要严格按照Debug版链接Debug版本的库,Release版本链接Release版本的库。因为是中间状态所以在VS2015之前,不同版本VS编译的静态库都不能通用,必须要相同版本才能编译链接。VS2015以后微软队各个版本的静态库abi做了兼容,所以VS2015后大部分静态库可以通用。

如果Debug版C++程序链接Release版静态库时,链接会报错,以下是VS2022的报错:

liba.lib(a.cpp.obj) : error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“0”不匹配值“2”(main.cpp.obj 中)
liba.lib(a.cpp.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MD_DynamicRelease”不匹配值“MDd_DynamicDebug”(main.cpp.obj 中)
LINK : warning LNK4098: 默认库“MSVCRT”与其他库的使用冲突;请使用 /NODEFAULTLIB:library
E:\Study\StudyProject\cmake\lib_debug_release\main.exe : fatal error LNK1319: 检测到 2 个不匹配项

这是因为Debug版和Release版默认使用的vc++ 运行时库不相同,默认情况下Debug版使用/MDd,Release版使用/MD,两者不相同导致报错。

所以在链接库时需要区分Debug版和Release版。在CMake可以如下设置:

target_link_libraries(target $<$<CONFIG:Release>:liba.lib> $<$<CONFIG:Debug>:libad.lib>)

C语言静态库

上面说的都是关于C++的,实际上如果一个库是使用C开发的,那么这个库不会受VC++运行库的影响,也就是说你可以在Debug程序中链接一个C开发的Release的静态库。

很多开源库都是使用C开发的,所以在编译这些库的静态库时,只需要编译一个Release版。

参考

/MD, -MT, -LD (Use Run-Time Library) | Microsoft Learn

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值