c++ - 泄漏 sanitizer 检测泄漏

标签 c++ memory-leaks address-sanitizer

我正尝试使用 valgrind、gperftools 和 libasan 等工具在更复杂的系统中查找内存泄漏。我遇到了无法消除的漏洞,所以我制作了我能想到的最简单的程序。

为什么 LeakSanitizer 仍然报告泄漏?

这是我的主文件:test.cc

// File: test.cc

int main()
{
    unsigned char* data = new unsigned char[1024];
    delete[] data;
    data = 0;

    return 0;
}

这是我的生成文件:

# Makefile

CC=g++
FLAGS=--std=c++11 -O0 -g -I. -fsanitize=address -fno-omit-frame-pointer -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
TGT=run
LINK=-static-libasan -ltcmalloc

all: $(TGT)

$(TGT): 
        $(CC) $(FLAGS) test.cc -o $(TGT) $(LINK)

clean:
        rm -f $(TGT)

你可以运行程序:

env ASAN_OPTIONS=symbolize=1 ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-3.8 ./run

分析是:

=================================================================
==23139==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x481492 in operator new(unsigned long) (/home/user/tests/cpp/leakTest/basic/run+0x481492)
    #1 0x7f46c64bf0dd in InitModule src/malloc_extension.cc:212

SUMMARY: AddressSanitizer: 8 byte(s) leaked in 1 allocation(s).

我的系统:

user@computer:~$ lsb_release -a
LSB Version:    core-9.20160110ubuntu0.2-amd64:core-9.20160110ubuntu0.2-noarch:security-9.20160110ubuntu0.2-amd64:security-9.20160110ubuntu0.2-noarch
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.3 LTS
Release:    16.04
Codename:   xenial

user@computer:~/$ uname -a
Linux computer 4.4.0-103-generic #126-Ubuntu SMP Mon Dec 4 16:23:28 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

user@computer:~/$ dpkg -l | grep asan
ii  libasan2:amd64                                5.4.0-6ubuntu1~16.04.5                       amd64        AddressSanitizer -- a fast memory error detector

user@computer:~/$ dpkg -l | grep llvm
ii  libllvm3.6v5:amd64                            1:3.6.2-3ubuntu2                             amd64        Modular compiler and toolchain technologies, runtime library
ii  libllvm3.8:amd64                              1:3.8-2ubuntu4                               amd64        Modular compiler and toolchain technologies, runtime library
ii  libllvm4.0:amd64                              1:4.0-1ubuntu1~16.04.2                       amd64        Modular compiler and toolchain technologies, runtime library
ii  llvm                                          1:3.8-33ubuntu3.1                            amd64        Low-Level Virtual Machine (LLVM)
ii  llvm-3.8                                      1:3.8-2ubuntu4                               amd64        Modular compiler and toolchain technologies
ii  llvm-3.8-dev                                  1:3.8-2ubuntu4                               amd64        Modular compiler and toolchain technologies, libraries and headers
ii  llvm-3.8-runtime                              1:3.8-2ubuntu4                               amd64        Modular compiler and toolchain technologies, IR interpreter
ii  llvm-runtime                                  1:3.8-33ubuntu3.1                            amd64        Low-Level Virtual Machine (LLVM), bytecode interpreter

user@computer:~/$ dpkg -l | grep tcmalloc
ii  libtcmalloc-minimal4                          2.4-0ubuntu5.16.04.1                         amd64        efficient thread-caching malloc

user@computer:~/$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.5' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.5) 

user@computer:~/$ dpkg -l | grep libstdc
ii  libstdc++-5-dev:amd64                         5.4.0-6ubuntu1~16.04.5                       amd64        GNU Standard C++ Library v3 (development files)
ii  libstdc++6:amd64                              5.4.0-6ubuntu1~16.04.5                       amd64        GNU Standard C++ Library v3

编辑:嗯。如果我将 Makefile 中 asan 的链接从“-static-libasan”更改为“-lasan”,则不会报告任何泄漏。我不应该与 -static-libasan 链接吗?

最佳答案

我对 tcmalloc 不是很熟悉,但它似乎是故意泄露那个对象。 指向泄漏:

Direct leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x481492 in operator new(unsigned long) (/home/user/tests/cpp/leakTest/basic/run+0x481492)
    #1 0x7f46c64bf0dd in InitModule src/malloc_extension.cc:212

与此源代码 ( github ) 相关:

static void InitModule() {
  current_instance = new MallocExtension; // reported leak
#ifndef NO_HEAP_CHECK
  HeapLeakChecker::IgnoreObject(current_instance);
#endif
}

据报道,某些 valgrind 版本也检测到:
https://github.com/gperftools/gperftools/issues/758

关于c++ - 泄漏 sanitizer 检测泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47931207/

相关文章:

Clang 的 ASan 不检测悬空指针的使用

c++ - 如何使用 shellscalingapi.h 解决 C++ Windows 应用程序中的此链接器错误

c++ - 有什么方法可以创建一个可以作为参数传递的 16 字节对齐的类

c++ - 在生产中使用 Address Sanitizer 或其他未定义的行为 sanitizer ?

c++ - ASAN 检测到与动态加载的库共享的类的 vtable 的 ODR 违规

Delphi 7.0和内存泄漏?

c++ - 将托管 C++ 从 vs2003 移植到 vs2008 的问题

c++ - 加权 boolean 值 - 缩放

c++ - 通过智能指针查找谁创建了对象

java - java程序执行后如何释放内存