在CMake中使用适用于Xcode的AddressSanitizer的正确方法是什么

时间:2017-06-02 03:50:50

标签: c++ cmake clang address-sanitizer

我已添加了AddressSanitizer标志,如下所示:

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链接。
  3. 那么这两种解决方案的问题是什么?

    • 使用解决方案#1时,我必须在Xcode中手动打开目标方案,并添加指向DYLD_INSERT_LIBRARIES的{​​{1}}环境变量。
    • 使用解决方案#2时,ASan库的路径因计算机而异。

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

    非常感谢任何帮助。

6 个答案:

答案 0 :(得分:10)

您还需要向链接器提供标志。我是这样做的:

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")

答案 1 :(得分:3)

cmake 3.13
介绍xcode schema的配置

在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

答案 2 :(得分:3)

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

cmake -DCMAKE_BUILD_TYPE=ASAN .

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

我不知道何时添加此选项。我也找不到任何文档。

答案 3 :(得分:0)

我建议创建您自己的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的AddressSanitizer(ASan)处于试验阶段,因此我在此处未提供MSVC方式。

  2. CMAKE_BUILD_TYPE未被多配置生成器(Xcode,Visual Studio等)使用,因此我提供了一个示例来首先进行检查。

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

  4. 您可能还需要配置CMAKE_MODULE_LINKER_FLAGS

用法:

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

答案 4 :(得分:0)

我发现其他答案无效,您需要在工具链文件中设置init变量:

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

答案 5 :(得分:0)

首先确保获得调试信息,例如将CMAKE_BUILD_TYPE设置为Debug

然后,如果目标是可执行文件或共享库,则可以设置这些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")