2017-12-21 10 views
0

Ich versuche, ein Speicherleck in einem komplizierteren System mit Tools wie Valgrind, Gperftools und libasan zu finden. Ich bekam Lecks, die ich nicht loswerden konnte, also machte ich das einfachste Programm, an das ich denken konnte.Leak Sanitizer Erkennung von Leck

Warum meldet LeakSanitizer immer noch Lecks?

Hier ist meine Hauptdatei: test.cc

// File: test.cc 

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

    return 0; 
} 

Hier mein Makefile ist:

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

Die Analyse ist:

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

Sie das Programm mit ausführen können:

================================================================= 
==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). 

Mein System:

[email protected]:~$ 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 

[email protected]:~/$ 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 

[email protected]:~/$ dpkg -l | grep asan 
ii libasan2:amd64        5.4.0-6ubuntu1~16.04.5      amd64  AddressSanitizer -- a fast memory error detector 

[email protected]:~/$ 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 

[email protected]:~/$ dpkg -l | grep tcmalloc 
ii libtcmalloc-minimal4       2.4-0ubuntu5.16.04.1       amd64  efficient thread-caching malloc 

[email protected]:~/$ 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) 

[email protected]:~/$ 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 

EDIT: Hmm. Wenn ich die Verknüpfung von asan in meinem Makefile von '-static-libasan' nach '-lasan' ändere, werden keine Lecks gemeldet. Sollte ich nicht mit -static-libasan verlinken?

+0

eine Chance, dass LeakSanitizer hängt vom Rahmenzeiger ab? –

+0

Statische Verknüpfung sollte in Ordnung sein, würde ich eher denken, dass die falsche positive statische Verbindung ist eine Einschränkung des Programms und nicht ein Problem mit der statischen Bibliothek. –

+0

@JustinRandall Das Entfernen von '-fno-omit-frame-pointer' hat keinen Unterschied gemacht. Was wäre die Begrenzung des Programms? Entschuldigung, ich bin mit diesem Debuggen nicht besonders vertraut. – vincent

Antwort

1

Ich bin nicht vertraut mit tcmalloc, aber es scheint, dass es dieses Objekt absichtlich leckt. Die spitz auszulaufen:

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 

Korrelate mit diesem Quellcode (github):

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

Es wurde auch von einigen valgrind Versionen erkannt gemeldet werden:
https://github.com/gperftools/gperftools/issues/758

+0

Hm. Kurz vor dieser Funktionsdeklaration wird current_instance als statische Variable deklariert. Dann gibt die Funktion nach InitModule die current_instance (als Singleton) zurück. Warum sollte das ein Leck sein? – vincent

+0

@vincent Da diese statische Zuweisung dynamisch ist, wird erwartet, dass sie vor dem Programmende aufgehoben wird. Ich denke, es gibt keine Unterscheidung zwischen Statik und Nicht-Statik in Valgrind/Asan.Manchmal ist es sinnvoll, die Freigabe einiger Objekte zu vermeiden und das Betriebssystem diesen Speicher freizugeben, wenn das Programm abstürzt (dies könnte die für tcmalloc getroffene Entwurfsauswahl sein). Siehe auch diese Antwort: https://stackoverflow.com/questions/10572610/memory-leaks-when-using-a-singleton – valiano

+0

Ok, das macht Sinn. Vielen Dank. – vincent