Windows上,习惯将debug模式下生成的动态库名后缀添加D 以作和release区分。

debug和release的动态库是否可以混用

现象

使用一些第三方的dll,比如opencv,会分别生成debug和release的dll,在exe中必须要引用指定版本的dll,不能混用,否则会出错;

但是还有一些第三方的dll,比如halcon,只提供给用户release的dll,用户的debug版和release版的exe都可以引用此dll。

原因

比如debug的exe调用release编译生成的dll,接口函数的参数如果使用std::vector或者std::string之类的东西,肯定会崩。因为stl在release和debug下实现不同。std::string在debug和release环境中的内存大小是不一致的。 如果混用,会出现内存奔溃现象。

结论

不含stl库的debug动态库和release动态库在debug或release项目中都可以使用;

含有stl的debug动态库和release动态库在项目中不能混用,debug项目必须用debug库,release项目必须用release库 ;

内存谁分配谁释放,动态库导出函数不要用stl,仅使用基本类型或接口;

cmake中配置debug与release的对应库

cmake创建一个项目A,A引入动态库B,cmake怎么配置A链接动态库B的debug和release对应的库呢。

通过配置target_link_libraries的参数可以进行配置:

1
2
3
target_link_libraries(${PROJECT_NAME} PRIVATE
debug ${sdk_LIBRARY_debug}
optimized ${sdk_LIBRARY_release} )

其中。${sdk_LIBRARY_debug}是动态库debug模式下的绝对路径。 同理,${sdk_LIBRARY_release}是动态库release模式下的绝对路径。而他们的定义通过再findsdk.cmake文件中配置:

1
2
3
4
5
6
7
8
9
10
11
FIND_PATH(sdk_INCLUDE_DIR sdk.h ${CMAKE_CURRENT_SOURCE_DIR}/sdk/include)

FIND_LIBRARY(sdk_LIBRARY_release sdk.lib ${CMAKE_CURRENT_SOURCE_DIR}/sdk/lib/release)

FIND_LIBRARY(sdk_LIBRARY_debug sdkD.lib ${CMAKE_CURRENT_SOURCE_DIR}/sdk/lib/debug)

set(sdk_FOUND FALSE)
if (sdk_INCLUDE_DIR AND sdk_LIBRARY_release AND sdk_LIBRARY_debug)
set(sdk_FOUND TRUE)
endif()

后续使用通过find_package(sdk)。

如何生成debug和release的动态库

Debug的动态库一般有后缀d,在CMakeLists.txt中添加:

1
set(CMAKE_DEBUG_POSTFIX d)

这样编译出来的Debug版本的动态库就有了d

CMakeLists.txt文件的编译命令:

1
2
3
cmake . -B build # create build dir

cmake --build build --config=Release # or Debug

release生成pdb调试文件

CmakeLists.txt中添加以下内容,可生成pdb文件,在调试dump文件时有用。

1
2
3
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi -DQT_MESSAGELOGCONTEXT")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")

上面的可以按需组合或无脑全加入CMakeLists.txt。需要添加三行标志:

  • 第一行:告诉编译器生成调试信息
  • 第二行:告诉链接器生成exe时加入调试信息
  • 第三行:告诉链接器生成dll时加入调试信息