If I compile the following code with g++ (version 8.5.3 and also 11.2), memory leaks are shown, which I don't understand.
#include <string>
#include <vector>
#include <filesystem>
#include <iostream>
auto getV() -> std::string {
return "string from function";
}
auto getP() -> std::filesystem::path {
throw std::string{"exception"};
}
auto getA( const std::vector<std::string>& p ) {
auto a = std::vector<std::string>{
"--t",
getV(),
"--a",
( getP() / "test" ).string(),
"--",
};
a.insert(a.end(), p.begin(), p.end());
return a;
}
auto main() -> int {
try {
getA({"v1", "v2"});
} catch ( const std::string& s ) {
std::cerr << "Caught: " << s << std::endl;
}
return 0;
}
Nothing special for compiling the code:
$ g++ -fsanitize=address -Wall -Wextra -std=c++17 -g a.cpp -lstdc++fs
valgrind as well as the GCC address sanitizer show:
$ ./a.out
Caught: exception
=================================================================
==13329==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 21 byte(s) in 1 object(s) allocated from:
#0 0x7f72e4591c17 in operator new(unsigned long) ../../../../gcc-11.2.0/libsanitizer/asan/asan_new_delete.cpp:99
#1 0x40505d in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) /opt/gnu/gcc/include/c++/11.2.0/bits/basic_string.tcc:219
#2 0x403ff9 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::allocator<char> >(char const*, std::allocator<char> const&) /opt/gnu/gcc/include/c++/11.2.0/bits/basic_string.h:539
#3 0x402754 in getV[abi:cxx11]() /workspace/a.cpp:8
#4 0x402aa8 in getA(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) /workspace/a.cpp:22
#5 0x403427 in main /workspace/a.cpp:30
#6 0x7f72e3818554 in __libc_start_main (/lib64/libc.so.6+0x22554)
Direct leak of 17 byte(s) in 1 object(s) allocated from:
#0 0x7f72e4591c17 in operator new(unsigned long) ../../../../gcc-11.2.0/libsanitizer/asan/asan_new_delete.cpp:99
#1 0x40505d in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) /opt/gnu/gcc/include/c++/11.2.0/bits/basic_string.tcc:219
#2 0x403ff9 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::allocator<char> >(char const*, std::allocator<char> const&) /opt/gnu/gcc/include/c++/11.2.0/bits/basic_string.h:539
#3 0x402ad9 in getA(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) /workspace/a.cpp:22
#4 0x403427 in main /workspace/a.cpp:30
#5 0x7f72e3818554 in __libc_start_main (/lib64/libc.so.6+0x22554)
SUMMARY: AddressSanitizer: 38 byte(s) leaked in 2 allocation(s).
This is from GCC 11.2 wherease GCC 8.5.3 actually has 1 leaks more. If I compile the exact same code using clang, there are no leaks. I also tried https://www.onlinegdb.com/ and it has the leaks as well.
Can anyone shed some more light on what's going on here? Is this a compiler bug in GCC or am I doing something wrong? If it is me, is there a way to detect such problems at compile time?