什么是正确的方法来启用 CMake 中的地址消毒器在 Xcode 工作

我添加了如下地址消毒器标志:

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")

当使用 Unix Makefiles时,一切都构建和运行得很好。

问题出现在生成 Xcode 项目时,它只是不想链接,因为它找不到 ASan 库。

我已经找到了两个解决方案,但是决定不使用它们,因为它们不能仅仅使用 CMake 自动化:

  1. -Wl,-undefined,dynamic_lookup添加到链接标志中,因此它跳过了链接到动态库的步骤。
  2. 直接与 libclang_rt.asan_osx_dynamic.dylib连接。

那么这两种解决方案有什么问题呢?

  • 在使用解决方案 # 1时,我必须手动打开 Xcode 的目标方案,并添加指向 libclang_rt.asan_osx_dynamic.dylibDYLD_INSERT_LIBRARIES环境变量。
  • 当使用解决方案 # 2时,ASan 库的路径在不同计算机之间有所不同。

此外,作为另一个解决方案,我尝试从 Xcode 目标模式启用 Address Sanitizer 标志,但有趣的是,它没有检测到我添加的问题,所以我没有将其列为解决方案,因为它未能通过我的测试。

任何帮助都将不胜感激。

62226 次浏览

你也需要提供链接器的标志。我是这样做的:

set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")

Cmake 3.13
引入 Xcode 模式 < br >

的配置

在 CMake 中

cmake_minimum_required(VERSION 3.13)
set(CMAKE_XCODE_GENERATE_SCHEME ON)
set(CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER ON)
set(CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN ON)

建造时

xcodebuild -enableAddressSanitizer YES

我目前找到的最简单的解决方案是

cmake -DCMAKE_BUILD_TYPE=ASAN .

我更喜欢这个选项,因为它表达了意图(运行消毒程序) ,而不是修改许多标志。

我不知道这个选项是什么时候添加的。我也找不到关于它的任何文档。

我建议建立你自己的 Asan 档案。

get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)


if(isMultiConfig)
if(NOT "Asan" IN_LIST CMAKE_CONFIGURATION_TYPES)
list(APPEND CMAKE_CONFIGURATION_TYPES Asan)
endif()
else()
set(allowedBuildTypes Asan Debug Release RelWithDebInfo MinSizeRel)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowedBuildTypes}")


if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE IN_LIST allowedBuildTypes)
message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}")
endif()
endif()


set(CMAKE_C_FLAGS_ASAN
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C compiler for Asan build type or configuration." FORCE)


set(CMAKE_CXX_FLAGS_ASAN
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C++ compiler for Asan build type or configuration." FORCE)


set(CMAKE_EXE_LINKER_FLAGS_ASAN
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address" CACHE STRING
"Linker flags to be used to create executables for Asan build type." FORCE)


set(CMAKE_SHARED_LINKER_FLAGS_ASAN
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address" CACHE STRING
"Linker lags to be used to create shared libraries for Asan build type." FORCE)

备注:

  1. 使用 MSVC 的 Windows 地址消毒器(ASan)正处于试验阶段,因此我没有在这里提供 MSVC 方式。

  2. 多配置生成器(Xcode、 VisualStudio 等)不使用 CMAKE_BUILD_TYPE,因此我提供了一个示例来首先检查这一点。

  3. CMAKE_BUILD_TYPE的默认值是 空字符串。用户可以在 cmake 命令行中将 CMAKE_BUILD_TYPE设置为任何值。因此,我们检查这两种情况,并确保处理的是已知的构建类型(如果提供的话)。

  4. 您可能还需要配置 CMAKE_MODULE_LINKER_FLAGS

用法:

$ cmake \
-DCMAKE_BUILD_TYPE=Asan \
...
...

我发现其他的答案都不起作用,你需要在你的工具链文件中设置 init 变量:

set(CMAKE_EXE_LINKER_FLAGS_INIT "-fsanitize=address -fno-omit-frame-pointer")

首先确保使用调试信息,例如 将 ABC0设置为 Debug通过 GCC/Clang 的 -g标志。

然后,如果您的目标是一个可执行程序或共享库,那么您可以设置这些 cmake 变量:

  • CMAKE_EXE_LINKER_FLAGS
  • CMAKE_EXE_LINKER_FLAGS_DEBUG
  • CMAKE_SHARED_LINKER_FLAGS
  • CMAKE_SHARED_LINKER_FLAGS_DEBUG

例如,当你的目标是一个可执行文件:

set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")

当您的目标是一个共享库时:

set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")

但是,当您的可执行文件依赖于一个静态库,并且您希望使用 asan 来检查您的静态库时,那么您必须这样设置:

set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")

由于这些天来最受欢迎的答案是错误的,而且我没有得到适当的 cmake 解决方案来阅读这个帖子,我想我应该在写这篇文章的时候提到正确的方法,这样下一位读者就不需要花太多时间在这上面了。

此解决方案的思想是将 -fsanitize=address传递给编译器和链接器标志。

如果您希望同时为所有目标启用此选项,可以使用 Add _ edit _ options 添加 _ 编译 _ 选项Add _ link _ options。如果您有多个(可能是大量的)目标,这是有意义的。

add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)

或者,您也可以使用 目标 _ 编译 _ 选项Target _ link _ options为特定目标设置这些。如果您不希望这种方法适用于所有目标,那么这样做可能更有意义。

target_compile_options(asan-target PRIVATE -fsanitize=address)
target_link_options(asan-target PRIVATE -fsanitize=address)