gcc - how to use address sanitizer - c++

I use gcc 4.8.5 on linux. I want to use address sanitizer but it doesn't return any information about the program. Flags:
SET(CMAKE_CXX_FLAGS "-Wall -Wno-error -g -std=c++11 -fno-omit-frame-pointer -fsanitize=address")
SET(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
Linked libraries:
target_link_libraries(testcpp asan)
The test program with a memory leak:
int main()
{
int *prt = new int;
return 0;
}
What is wrong ?

With GCC7 on a recent Debian/Sid/x86-64 I compiled this
// file irbis.cc
int main()
{
int *prt = new int;
return 0;
}
using
g++ -fsanitize=address -g3 -std=c++11 irbis.cc -o irbis
and at execution of ./irbis a leak is rightfully detected :
=================================================================
==22742==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 4 byte(s) in 1 object(s) allocated from:
#0 0x7f77ea911340 in operator new(unsigned long)
(/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdb340)
#1 0x55ea91cca81b in main /home/basile/tmp/irbis.cc:4
#2 0x7f77e9c1f2e0 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
SUMMARY: AddressSanitizer: 4 byte(s) leaked in 1 allocation(s).
So upgrade your GCC compiler (to at least GCC6). I do know that GCC4.8 had incomplete support for address sanitizer & C++11 (BTW, GCC4.8 is obsolete, and so is GCC5, in november 2017).

The cause of the problem might be that the main doesn't use ptr so it probably was optimized out entierly. Consider this instead:
// file irbis.cc
int main()
{
int *prt = new int;
return *ptr;
}

Related

ASAN is not able to detect memory leak for unused delete after new

Hello stackoverflow community, I am creating a memory leak to use ASAN and detect memory leaks.
$ export MallocNanoZone='0' # to avoid https://stackoverflow.com/q/64126942/9497703 on OS X
$ cat new_delete.cc
class Dummy {
public:
Dummy(int x) {
sz = x;
}
private:
int sz;
};
void func(int i) {
Dummy* p = new Dummy(i);
if (i < 50) {
// If return from here then there is a memory leak on the
// heap. Dummy is not freed.
return;
}
// Do useful things.
delete p;
}
int main() {
func(10);
}
$ clang++ -fsanitize=address -g -O0 new_delete.cc
$ ./a.out
I was expecting ASAN to detect this memory leak. However, it didn't.
Can anyone point out what I am missing here? I am using OS X and following clang version:
$ clang++ --version
Apple clang version 12.0.0 (clang-1200.0.32.28)
Target: x86_64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
This is a known issue - algorithm used in Lsan is probabilistic and does not guarantee that all leaks are detected (see #937 for details). E.g. in your case if we change main to
int main() {
int a[100];
func(10);
}
clang starts to detect the leak:
$ clang++ -fsanitize=address new_delete.cc && ./a.out
=================================================================
==349258==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 4 byte(s) in 1 object(s) allocated from:

ASAN Leak detection does not detect new (ptr) memory allocation leak

Is this a feature or a bug in ASAN? If I have this code:
class Foo {
int x = 5;
int z = 10;
};
int main() {
void *memory = malloc(sizeof(Foo));
Foo *ptr = new(memory) Foo();
ptr = nullptr;
}
ASAN reports no leaks. If I remove the Foo *ptr = new(memory) Foo(); suddenly I get leak:
Direct leak of 8 byte(s) in 1 object(s) allocated from:
0x7f00b7a80a89 __interceptor_malloc asan_malloc_linux.cpp:69
0x55dfa164d1ca main main.cpp:12
0x7f00b74a72cf (libc.so.6+0x232cf)
Compiler version: c++ (GCC) 12.2.0
Compile commands:
[1/2] /usr/sbin/c++ -g -fsanitize=address -fsanitize=leak -std=gnu++14 -MD -MT CMakeFiles/test.dir/main.cpp.o -MF CMakeFiles/test.dir/main.cpp.o.d -o CMakeFiles/test.dir/main.cpp.o -c /src/self/test/main.cpp
[2/2] : && /usr/sbin/c++ -g -fsanitize=address -fsanitize=leak CMakeFiles/test.dir/main.cpp.o -o test && :
OS: Linux WORKSTATION 5.19.4-zen1-1-zen #1 ZEN SMP PREEMPT_DYNAMIC Thu, 25 Aug 2022 17:31:19 +0000 x86_64 GNU/Linux

Why is address sanitizer not detecting this simple memory leak?

Does anybody have any idea why address sanitizer is not flagging this very obvious memory leak
class A {
public:
A() = default;
};
TEST_F(LibrdfSerializerTests, Test) {
A* a = new A;
}
built with the following added to cmake:
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")
You can try using the ASAN_OPTIONS=detect_leaks=1 while executing the binary to detect leaks. Using the example from the documentation
❯ cat leak.c
#include <stdlib.h>
void *p;
int main() {
p = malloc(7);
p = 0; // The memory is leaked here.
return 0;
}
Compile the program
clang -fsanitize=address -g leak.c
and then execute it as follows:
ASAN_OPTIONS=detect_leaks=1 ./a.out
Output:
=================================================================
==63987==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 7 byte(s) in 1 object(s) allocated from:
#0 0x1034c109d in wrap_malloc+0x9d (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x4609d)
#1 0x103477ef8 in main leak.c:4
#2 0x7fff6b30fcc8 in start+0x0 (libdyld.dylib:x86_64+0x1acc8)
SUMMARY: AddressSanitizer: 7 byte(s) leaked in 1 allocation(s).
Same for CPP
❯ cat memory-leak.cpp
#include <cstdlib>
#include <cstdio>
class A {
public:
A() = default;
};
int main() {
char const* asanOpt = std::getenv("ASAN_OPTIONS");
std::printf("%s\n", asanOpt);
A* a = new A;
return 0;
}
Compile it
clang++ -g memory-leak.cpp -fsanitize=address
While executing the binary, use the option to enable leak detections
ASAN_OPTIONS=detect_leaks=1 ./a.out
Output:
detect_leaks=1
=================================================================
==69309==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1 byte(s) in 1 object(s) allocated from:
#0 0x109ea556d in wrap__Znwm+0x7d (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x5256d)
#1 0x109e4bf48 in main memory-leak.cpp:7
#2 0x7fff6b30fcc8 in start+0x0 (libdyld.dylib:x86_64+0x1acc8)
SUMMARY: AddressSanitizer: 1 byte(s) leaked in 1 allocation(s).
Tested on:
MacOS 10.15
With clang
clang version 10.0.1
Target: x86_64-apple-darwin19.6.0
Thread model: posix

Why does the memory-sanitizer report use of an uninitialized value for std::map?

I'm using manjaro linux on x86-64. Memory-sanitizer in clang version 10.0.1 reported a use of uninitialized value error in std::map, which quite surprised me. Did I do something wrong?
$ cat test.cpp
#include <map>
int main() {
std::map<int, int> test;
test.insert({1,2});
}
$ clang++ -fsanitize=memory test.cpp && ./a.out
==51936==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x562889eaad9a (/tmp/build/a.out+0x9fd9a)
#1 0x562889eaae28 (/tmp/build/a.out+0x9fe28)
#2 0x562889eaaba1 (/tmp/build/a.out+0x9fba1)
#3 0x562889eaa51e (/tmp/build/a.out+0x9f51e)
#4 0x562889eaa087 (/tmp/build/a.out+0x9f087)
#5 0x7f418e02b151 (/usr/lib/libc.so.6+0x28151)
#6 0x562889e2b1dd (/tmp/build/a.out+0x201dd)
SUMMARY: MemorySanitizer: use-of-uninitialized-value (/tmp/build/a.out+0x9fd9a)
Exiting
FWIW it looks like libc++ is more MSAN-friendly than stdlibc++ because compiling a similar
#include <map>
#include <string>
int main(int argc, char** argv) {
std::map<int, std::string> m;
m[argc] = argv[argc - 1];
return 0;
}
code with the latter and running
% clang++ -fsanitize=memory -fno-omit-frame-pointer -g -O2 umr.cpp
results in a similar error, but doing
% clang++ -fsanitize=memory -fno-omit-frame-pointer -stdlib=libc++ -g -O2 umr.cpp && ./a.out
works fine (clang 13, Debian Sid).
When using MemorySanitizer, all libraries you use must be compiled with MemorySanitizer. Otherwise, there is a risk of false positives. This includes the C++ standard library itself.
You will find instructions for compiling libc++ with MemorySanitizer in the official sanitizers wiki:
https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo

Valgrind is not instrumenting: "total heap usage: 0 allocs, 0 frees, 0 bytes allocated"

Even after introducing an intentional memory leak valgrind shows:
==13483== HEAP SUMMARY:
==13483== in use at exit: 0 bytes in 0 blocks
==13483== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==13483==
==13483== All heap blocks were freed -- no leaks are possible
The executable was compiled with G++ 4.1.2 and 4.6.2 with:
g++ -ftemplate-depth-128 -O0 -fno-inline -Wall -pedantic -g -pthread -Wno-long-long -Wno-uninitialized <snipped definitions and include directives from the build system>
I've tried with Valgrind 3.5.0 and 3.6.1 like:
valgrind --leak-check=full --undef-value-errors=no --show-reachable=yes <executable args>
Within the framework of the library I'm working on, I'm using a simple test case:
#include "pwiz/utility/misc/Std.hpp"
#include "pwiz/utility/misc/Filesystem.hpp"
#include "pwiz/data/identdata/IdentDataFile.hpp"
using namespace pwiz::cv;
using namespace pwiz::data;
using namespace pwiz::identdata;
using namespace pwiz::util;
int main(int argc, char** argv)
{
vector<string> args(argv+1, argv+argc);
BOOST_FOREACH(const bfs::path& filename, args)
{
// intentional memory leak
IdentDataFile* idp = new IdentDataFile(filename.string());
IdentDataFile& id = *idp;
cout << filename.string() << " "
<< id.analysisCollection.spectrumIdentification[0]->activityDate << " "
<< id.analysisCollection.spectrumIdentification[0]->spectrumIdentificationListPtr->spectrumIdentificationResult.size()
<< "\n";
}
return 0;
}
Obviously I don't expect others to be able to compile this, but anyway I suspect it's something about the library that's tripping up valgrind so a simpler test case would be pointless. And I know that the for loop is being executed because I get the cout output during Valgrind execution. How can I debug it without simplifying further?
It boiled down to the linker options actually. I was compiling with -static, so valgrind did not have a chance to substitute its own malloc implementation. Unfortunate that valgrind doesn't at least warn about this though!