在CMake中启用AddressSanitizer的正确方法是什么?

Obj*_*Sal 22 c++ cmake clang address-sanitizer

我添加了AddressSanitizer标志如下:

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
Run Code Online (Sandbox Code Playgroud)

一切都在使用时构建并运行良好Unix Makefiles.

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

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

  1. 添加-Wl,-undefined,dynamic_lookup到链接的标志,因此它会跳过链接到动态库.
  2. libclang_rt.asan_osx_dynamic.dylib直接链接.

那么这两种解决方案的问题是什么?

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

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

任何帮助都感激不尽.

lpa*_*app 102

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

如果您想同时为所有目标启用此功能,可以使用add_compile_optionsadd_link_options。如果您有多个(可能是大量)目标,那么这是有意义的。

add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
Run Code Online (Sandbox Code Playgroud)

或者,您还可以使用target_compile_optionstarget_link_options为特定目标设置这些选项。如果您不希望将其应用于所有目标,这可能更有意义。

target_compile_options(asan-target PRIVATE -fsanitize=address)
target_link_options(asan-target PRIVATE -fsanitize=address)
Run Code Online (Sandbox Code Playgroud)

  • 我使用了第一种形式,但两者都为“$<$<CONFIG:Debug>:-fsanitize-address>”,因此它只会在调试版本中启用。 (4认同)

Maa*_*Vds 12

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

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")
Run Code Online (Sandbox Code Playgroud)

  • 第二行看起来不对我.八,双方应该是CMAKE_STATIC_LINKER_FLAGS_DEBUG,或CMAKE_LINKER_FLAGS_DEBUG. (3认同)
  • 现代 CMake:`string(APPEND CMAKE_CXX_FLAGS_DEBUG " -fno-omit...")` (2认同)
  • @Timmmm 直接摆弄`CMAKE_CXX_FLAGS` 无论如何都不是现代CMake。使用 `check_cxx_compiler_flag` 将是最接近的。 (2认同)
  • @Timmmm 发现得很好。谢谢。我犯了复制和粘贴错误。当然,我的意思是“target_compile_options”。 (2认同)
  • @Timmmm:您可以使用 add_compile/link_options 将其应用到每个目标。但如今这个答案是错误的。这些天刚刚用 cmake 添加了正确的内容。请在下面找到答案:/sf/answers/4919050531/ (2认同)

ser*_*hei 8

我建议创建您自己的 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)
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 带有 MSVC 的 Windows 的 AddressSanitizer (ASan) 处于实验阶段,因此我没有在这里提供 MSVC 方式。

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

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

  4. 还有CMAKE_MODULE_LINKER_FLAGS你可能想要配置。

用法:

$ cmake \
    -DCMAKE_BUILD_TYPE=Asan \
    ...
    ...
Run Code Online (Sandbox Code Playgroud)

  • 虽然与其他一些答案相比,这似乎有点复杂,但它似乎确实是最好的方法。您是偶然从《Professional CMake》一书中获得此信息的吗? (2认同)

小智 5

cmake 3.13
引入xcode模式的配置

在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)
Run Code Online (Sandbox Code Playgroud)

建立时

xcodebuild -enableAddressSanitizer YES
Run Code Online (Sandbox Code Playgroud)


Hax*_*raZ 5

首先确保有调试信息,例如设置CMAKE_BUILD_TYPEDebug传递-gGCC/Clang 标志。

然后,如果您的目标是可执行文件或共享库,那么您可以设置这些 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")
Run Code Online (Sandbox Code Playgroud)

当您的目标是共享库时:

set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
Run Code Online (Sandbox Code Playgroud)

然而,当你的可执行文件依赖于静态库并且你想使用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")
Run Code Online (Sandbox Code Playgroud)