CMake配置ASAN工具链时GCC9/10版本无法链接pthread问题求助
CMake配合GCC 9/10使用ASan链接pthread失败的解决方法
问题根源
- 变量名使用错误:你在ASan工具链中使用的
CMAKE_LINKER_FLAGS_INIT不是CMake的官方内置变量,正确的可执行文件链接参数初始化变量为CMAKE_EXE_LINKER_FLAGS_INIT,导致你配置的链接参数未完全生效。 - GCC低版本ASan的特性差异:GCC 11及以上版本的libasan默认依赖pthread库,而GCC 9、10版本的libasan仅提供
pthread_create等少数pthread接口的弱符号,不完整实现pthread功能。 - FindThreads模块的检测误判:CMake的
FindThreads模块检测线程库依赖时,会尝试编译最小测试用例判断是否需要额外加-pthread参数。在GCC 9/10加ASan的场景下,测试用例仅用到pthread_create,可以被libasan的弱符号满足,因此模块误认为不需要加-pthread,最终你的代码用到pthread_setspecific等libasan未实现的接口时就会链接失败。
而ubsan工具链不存在以上问题,是因为ubsan本身不提供任何pthread相关的符号,FindThreads可以正确检测到需要-pthread参数。
正确解决方法
直接在ASan工具链的编译和链接参数中显式加入-pthread,同时修正链接参数的变量名即可,修改后的asan.toolchain.cmake参考如下:
# asan.toolchain.cmake set (CMAKE_C_COMPILER gcc) set (CMAKE_CXX_COMPILER g++) set (CMAKE_CXX_STANDARD 14) # 编译参数新增-pthread set (CMAKE_CXX_FLAGS_INIT "-O0 -g -fsanitize=address -fno-omit-frame-pointer -fno-var-tracking-assignments -pthread") # 修正链接参数变量名,新增-pthread set (CMAKE_EXE_LINKER_FLAGS_INIT "-fsanitize=address -fno-omit-frame-pointer -pthread") # 如果需要构建共享库,额外加以下行 # set (CMAKE_SHARED_LINKER_FLAGS_INIT "-fsanitize=address -fno-omit-frame-pointer -pthread") set (CMAKE_BUILD_TYPE Debug)
替代方案
如果不想修改工具链文件,也可以在项目的CMakeLists.txt中显式为目标指定pthread参数:
add_executable (test main.cpp) target_link_libraries (test PRIVATE Threads::Threads) # 新增以下两行 target_compile_options(test PRIVATE -pthread) target_link_options(test PRIVATE -pthread)
内容的提问来源于stack exchange,提问作者David Brown
相关产品推荐
相关产品推荐

