使用 Clang 进行动态分析 - 抑制在 CMake 项目中忽略的外部库中的报告
Dynamic Analysis with Clang - Suppressing Reports in External Libraries Ignored in a CMake project
我正在尝试在 clang 编译器中使用 -fsanitize=address
feature,但我只想查看本地项目错误,因此我将忽略来自 3rdparty 库的传入错误,特别是我有一个项目被配置为忽略来自 dbus 的错误。
我的系统:
cmake 版本 3.9.5
Linux 主机名 4.14.0-2-amd64 #1 SMP Debian 4.14.7-1 (2017-12-22) x86_64 GNU/Linux
clang 版本 4.0.1-8 (tags/RELEASE_401/final)
目标:x86_64-pc-linux-gnu
线程模型:posix
安装目录:/usr/bin
我的mcve:
.
├── CMakeLists.txt
├── CTestConfig.cmake
├── CTestCustom.cmake
├── MyASan.supp
└── src
├── CMakeLists.txt
├── entityitem.cc
├── mainwindow.cc
├── mainwindow.h
└── mainwindow.ui
1 directory, 10 files
CMakeLists.txt:
cmake_minimum_required(VERSION 3.9.0 FATAL_ERROR)
project(SanitizerTest)
set(CMAKE_C_STANDARD 14)
set(CMAKE_CXX_STANDARD 14)
include(CTest)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src)
CTestConfig.cmake:
## This file should be placed in the root directory of your project.
## Then modify the CMakeLists.txt file in the root directory of your
## project to incorporate the testing dashboard.
##
## # The following are required to submit to the CDash dashboard:
## ENABLE_TESTING()
## INCLUDE(CTest)
set(CTEST_PROJECT_NAME "Exampling")
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "localhost:8090")
set(CTEST_DROP_LOCATION "/submit.php?project=Exampling")
set(CTEST_DROP_SITE_CDASH TRUE)
CTestCustom.cmake:
set(CTEST_CMAKE_GENERATOR "Unix Makefiles")
set(CTEST_MEMORYCHECK_TYPE "AddressSanitizer")
set(CTEST_SOURCE_DIRECTORY ${CTEST_SCRIPT_DIRECTORY})
set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE ${CTEST_SOURCE_DIRECTORY}/MyASan.supp)
ctest_empty_binary_directory("${CTEST_BINARY_DIRECTORY}")
set(CTEST_MEMORYCHECK_TYPE "AddressSanitizer")
ctest_start(Experimental)
set(CONFIGURE_OPTIONS
"-DCMAKE_BUILD_TYPE=Debug"
"-DCMAKE_CXX_FLAGS=-g -O0 -fno-omit-frame-pointer -fsanitize=address"
"-DCMAKE_C_FLAGS=-g -O0 -fno-omit-frame-pointer -fsanitize=address"
"-DCMAKE_GENERATOR=Unix Makefiles"
"-DCMAKE_CXX_COMPILER=clang"
"-DCMAKE_C_COMPILER=clang"
)
ctest_configure(OPTIONS "${CONFIGURE_OPTIONS}")
ctest_build()
MyASan.supp:
interceptor_via_lib:dbus-1
src/CMakeLists.txt:
find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
add_library(module
${CMAKE_CURRENT_SOURCE_DIR}/mainwindow.cc)
target_include_directories(module INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/module_autogen/include>)
target_link_libraries(module
PUBLIC stdc++
PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets)
add_executable(main
${CMAKE_CURRENT_SOURCE_DIR}/entityitem.cc)
target_link_libraries(main module)
src/entityitem.cc:
#include <QtWidgets/QApplication>
#include <QtCore/QDebug>
#include "mainwindow.h"
int main(int argc, char *argv[]) {
QApplication a{argc, argv};
MainWindow d;
qDebug() << d.width();
return EXIT_SUCCESS;
}
src/mainwindow.cc:
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
int *i{new int};
ui.setupUi(this);
}
src/mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "ui_mainwindow.h"
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private:
Ui::MainWindow ui;
};
#endif // MAINWINDOW_H
src/mainwindow.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>30</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
我的问题,从项目根目录执行:
mkdir build
cd build
ctest -DCTEST_BINARY_DIRECTORY="." --verbose -S ../CTestCustom.cmake
./src/main
然后输出是:
=================================================================
==24262==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 6912 byte(s) in 27 object(s) allocated from:
#0 0x4d0810 (/home/adacosta/WORK/fffffffffff/Sanitazer/build/src/main+0x4d0810)
#1 0x7f75480378ed (/usr/lib/x86_64-linux-gnu/libfontconfig.so.1+0x1d8ed)
Direct leak of 4 byte(s) in 1 object(s) allocated from:
#0 0x4d0810 (/home/adacosta/WORK/fffffffffff/Sanitazer/build/src/main+0x4d0810)
#1 0x7f75529b1097 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x90097)
#2 0x50a80f (/home/adacosta/WORK/fffffffffff/Sanitazer/build/src/main+0x50a80f)
#3 0x7f7550369f29 (/lib/x86_64-linux-gnu/libc.so.6+0x20f29)
Indirect leak of 4239 byte(s) in 5 object(s) allocated from:
#0 0x4d0c35 (/home/adacosta/WORK/fffffffffff/Sanitazer/build/src/main+0x4d0c35)
#1 0x7f754545b47c (/lib/x86_64-linux-gnu/libdbus-1.so.3+0x3247c)
Indirect leak of 1824 byte(s) in 57 object(s) allocated from:
#0 0x4d0a18 (/home/adacosta/WORK/fffffffffff/Sanitazer/build/src/main+0x4d0a18)
#1 0x7f7548037fd8 (/usr/lib/x86_64-linux-gnu/libfontconfig.so.1+0x1dfd8)
.
.
.
如您所见,我有一个来自 dbus 库的 "Indirect leak of"。
解决方案:
- 将
set(CTEST_MEMORYCHECK_TYPE "AddressSanitizer")
改为
set(CTEST_MEMORYCHECK_TYPE "LeakSanitizer")
。
- 将
interceptor_via_lib:dbus-1
更改为 leak:libdbus-1
。
这将发送 LSAN_OPTIONS
而不是 ASAN_OPTIONS
到进程执行。
更多信息:https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#suppressions
我正在尝试在 clang 编译器中使用 -fsanitize=address
feature,但我只想查看本地项目错误,因此我将忽略来自 3rdparty 库的传入错误,特别是我有一个项目被配置为忽略来自 dbus 的错误。
我的系统: cmake 版本 3.9.5
Linux 主机名 4.14.0-2-amd64 #1 SMP Debian 4.14.7-1 (2017-12-22) x86_64 GNU/Linux
clang 版本 4.0.1-8 (tags/RELEASE_401/final) 目标:x86_64-pc-linux-gnu 线程模型:posix 安装目录:/usr/bin
我的mcve:
.
├── CMakeLists.txt
├── CTestConfig.cmake
├── CTestCustom.cmake
├── MyASan.supp
└── src
├── CMakeLists.txt
├── entityitem.cc
├── mainwindow.cc
├── mainwindow.h
└── mainwindow.ui
1 directory, 10 files
CMakeLists.txt:
cmake_minimum_required(VERSION 3.9.0 FATAL_ERROR)
project(SanitizerTest)
set(CMAKE_C_STANDARD 14)
set(CMAKE_CXX_STANDARD 14)
include(CTest)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src)
CTestConfig.cmake:
## This file should be placed in the root directory of your project.
## Then modify the CMakeLists.txt file in the root directory of your
## project to incorporate the testing dashboard.
##
## # The following are required to submit to the CDash dashboard:
## ENABLE_TESTING()
## INCLUDE(CTest)
set(CTEST_PROJECT_NAME "Exampling")
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "localhost:8090")
set(CTEST_DROP_LOCATION "/submit.php?project=Exampling")
set(CTEST_DROP_SITE_CDASH TRUE)
CTestCustom.cmake:
set(CTEST_CMAKE_GENERATOR "Unix Makefiles")
set(CTEST_MEMORYCHECK_TYPE "AddressSanitizer")
set(CTEST_SOURCE_DIRECTORY ${CTEST_SCRIPT_DIRECTORY})
set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE ${CTEST_SOURCE_DIRECTORY}/MyASan.supp)
ctest_empty_binary_directory("${CTEST_BINARY_DIRECTORY}")
set(CTEST_MEMORYCHECK_TYPE "AddressSanitizer")
ctest_start(Experimental)
set(CONFIGURE_OPTIONS
"-DCMAKE_BUILD_TYPE=Debug"
"-DCMAKE_CXX_FLAGS=-g -O0 -fno-omit-frame-pointer -fsanitize=address"
"-DCMAKE_C_FLAGS=-g -O0 -fno-omit-frame-pointer -fsanitize=address"
"-DCMAKE_GENERATOR=Unix Makefiles"
"-DCMAKE_CXX_COMPILER=clang"
"-DCMAKE_C_COMPILER=clang"
)
ctest_configure(OPTIONS "${CONFIGURE_OPTIONS}")
ctest_build()
MyASan.supp:
interceptor_via_lib:dbus-1
src/CMakeLists.txt:
find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
add_library(module
${CMAKE_CURRENT_SOURCE_DIR}/mainwindow.cc)
target_include_directories(module INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/module_autogen/include>)
target_link_libraries(module
PUBLIC stdc++
PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets)
add_executable(main
${CMAKE_CURRENT_SOURCE_DIR}/entityitem.cc)
target_link_libraries(main module)
src/entityitem.cc:
#include <QtWidgets/QApplication>
#include <QtCore/QDebug>
#include "mainwindow.h"
int main(int argc, char *argv[]) {
QApplication a{argc, argv};
MainWindow d;
qDebug() << d.width();
return EXIT_SUCCESS;
}
src/mainwindow.cc:
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
int *i{new int};
ui.setupUi(this);
}
src/mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "ui_mainwindow.h"
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private:
Ui::MainWindow ui;
};
#endif // MAINWINDOW_H
src/mainwindow.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>30</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
我的问题,从项目根目录执行:
mkdir build
cd build
ctest -DCTEST_BINARY_DIRECTORY="." --verbose -S ../CTestCustom.cmake
./src/main
然后输出是:
=================================================================
==24262==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 6912 byte(s) in 27 object(s) allocated from:
#0 0x4d0810 (/home/adacosta/WORK/fffffffffff/Sanitazer/build/src/main+0x4d0810)
#1 0x7f75480378ed (/usr/lib/x86_64-linux-gnu/libfontconfig.so.1+0x1d8ed)
Direct leak of 4 byte(s) in 1 object(s) allocated from:
#0 0x4d0810 (/home/adacosta/WORK/fffffffffff/Sanitazer/build/src/main+0x4d0810)
#1 0x7f75529b1097 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x90097)
#2 0x50a80f (/home/adacosta/WORK/fffffffffff/Sanitazer/build/src/main+0x50a80f)
#3 0x7f7550369f29 (/lib/x86_64-linux-gnu/libc.so.6+0x20f29)
Indirect leak of 4239 byte(s) in 5 object(s) allocated from:
#0 0x4d0c35 (/home/adacosta/WORK/fffffffffff/Sanitazer/build/src/main+0x4d0c35)
#1 0x7f754545b47c (/lib/x86_64-linux-gnu/libdbus-1.so.3+0x3247c)
Indirect leak of 1824 byte(s) in 57 object(s) allocated from:
#0 0x4d0a18 (/home/adacosta/WORK/fffffffffff/Sanitazer/build/src/main+0x4d0a18)
#1 0x7f7548037fd8 (/usr/lib/x86_64-linux-gnu/libfontconfig.so.1+0x1dfd8)
.
.
.
如您所见,我有一个来自 dbus 库的 "Indirect leak of"。
解决方案:
- 将
set(CTEST_MEMORYCHECK_TYPE "AddressSanitizer")
改为set(CTEST_MEMORYCHECK_TYPE "LeakSanitizer")
。 - 将
interceptor_via_lib:dbus-1
更改为leak:libdbus-1
。
这将发送 LSAN_OPTIONS
而不是 ASAN_OPTIONS
到进程执行。
更多信息:https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#suppressions