This is related to the following Valgrind bugzilla item https://bugs.kde.org/show_bug.cgi?id=358980 from comment 3 onwards. The leaks that I get are ==16702== HEAP SUMMARY: ==16702== in use at exit: 24,879 bytes in 29 blocks ==16702== total heap usage: 335 allocs, 306 frees, 233,296 bytes allocated ==16702== ==16702== 8 bytes in 1 blocks are definitely lost in loss record 1 of 15 ==16702== at 0x48447C2: malloc (vg_replace_malloc.c:446) ==16702== by 0x96A0A35: ??? ==16702== by 0x96B788F: ??? ==16702== by 0x969F1BB: ??? ==16702== by 0x40045B6: call_init (dl-init.c:74) ==16702== by 0x40045B6: call_init (dl-init.c:26) ==16702== by 0x40046AC: _dl_init (dl-init.c:121) ==16702== by 0x40015C1: _dl_catch_exception (dl-catch.c:215) ==16702== by 0x400B4FB: dl_open_worker (dl-open.c:829) ==16702== by 0x4001522: _dl_catch_exception (dl-catch.c:241) ==16702== by 0x400B903: _dl_open (dl-open.c:905) ==16702== by 0x4CA3F13: dlopen_doit (dlopen.c:56) ==16702== by 0x4001522: _dl_catch_exception (dl-catch.c:241) ==16702== by 0x4001678: _dl_catch_error (dl-catch.c:260) ==16702== by 0x4CA39F2: _dlerror_run (dlerror.c:138) ==16702== by 0x4CA3FCE: dlopen_implementation (dlopen.c:71) ==16702== by 0x4CA3FCE: dlopen@@GLIBC_2.34 (dlopen.c:81) ==16702== by 0x10917D: main (main.cpp:6) ==16702== ==16702== 96 bytes in 1 blocks are definitely lost in loss record 10 of 15 ==16702== at 0x484BEFF: calloc (vg_replace_malloc.c:1675) ==16702== by 0x96A0A6D: ??? ==16702== by 0x969F100: ??? ==16702== by 0x969F1D7: ??? ==16702== by 0x40045B6: call_init (dl-init.c:74) ==16702== by 0x40045B6: call_init (dl-init.c:26) ==16702== by 0x40046AC: _dl_init (dl-init.c:121) ==16702== by 0x40015C1: _dl_catch_exception (dl-catch.c:215) ==16702== by 0x400B4FB: dl_open_worker (dl-open.c:829) ==16702== by 0x4001522: _dl_catch_exception (dl-catch.c:241) ==16702== by 0x400B903: _dl_open (dl-open.c:905) ==16702== by 0x4CA3F13: dlopen_doit (dlopen.c:56) ==16702== by 0x4001522: _dl_catch_exception (dl-catch.c:241) ==16702== by 0x4001678: _dl_catch_error (dl-catch.c:260) ==16702== by 0x4CA39F2: _dlerror_run (dlerror.c:138) ==16702== by 0x4CA3FCE: dlopen_implementation (dlopen.c:71) ==16702== by 0x4CA3FCE: dlopen@@GLIBC_2.34 (dlopen.c:81) ==16702== by 0x10917D: main (main.cpp:6) ==16702== ==16702== LEAK SUMMARY: ==16702== definitely lost: 104 bytes in 2 blocks ==16702== indirectly lost: 0 bytes in 0 blocks ==16702== possibly lost: 0 bytes in 0 blocks ==16702== still reachable: 24,775 bytes in 27 blocks ==16702== suppressed: 0 bytes in 0 blocks ==16702== Reachable blocks (those to which a pointer was found) are not shown. ==16702== To see them, rerun with: --leak-check=full --show-leak-kinds=all I'm ignoring the still-reachables for now. Details: Arch linux updated on 24 Dec 2024 running in a VirtualBox VM [paulf@archlinux dlopen-leaks]$ lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Address sizes: 36 bits physical, 48 bits virtual Byte Order: Little Endian CPU(s): 1 On-line CPU(s) list: 0 Vendor ID: GenuineIntel Model name: Intel(R) Xeon(R) CPU W3520 @ 2.67GHz CPU family: 6 Model: 26 Thread(s) per core: 1 Core(s) per socket: 1 Socket(s): 1 Stepping: 5 BogoMIPS: 5335.55 Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopolo gy nonstop_tsc cpuid tsc_known_freq pni monitor ssse3 cx16 sse4_1 sse4_2 x2apic popcnt hypervisor lahf_lm pti Valgrind 3.24.0 (same with Valgrind built from git HEAD). gcc (GCC) 14.2.1 20240910 [paulf@archlinux dlopen-leaks]$ /lib/ld-linux-x86-64.so.2 --version ld.so (GNU libc) stable release version 2.40.
Please add a reproducer. The valgrind output is consistent with loading a shared object with dlopen, and the shared object has an ELF constructor that calls malloc (perhaps indirectly).
From the Valgrind item git clone https://github.com/leshe4ka46/dlopen-leaks cd dlopen-leaks mkdir build cmake .. make cd .. ./build/dlopen_test There are quite a few dependencies, particularly Qt6. I don't get a leak on Fedora 41, also glibc 2.40. I'll try to see if I can get any more info about the callstack entries that seem to be stripped.
(In reply to Paul Floyd from comment #2) > From the Valgrind item > > git clone https://github.com/leshe4ka46/dlopen-leaks > cd dlopen-leaks > mkdir build > cmake .. > make > cd .. > ./build/dlopen_test > > There are quite a few dependencies, particularly Qt6. > > I don't get a leak on Fedora 41, also glibc 2.40. > > I'll try to see if I can get any more info about the callstack entries that > seem to be stripped. The reproducer does not run under valgrind because it conflicts with Address Sanitizer. If you can reproduce it on Fedora 41, please run the reproducer under valgrind with: DEBUGINFOD_URLS=https://debuginfod.fedoraproject.org/ valgrind build/dlopen_test
I forgot, you need to comment out asan: diff --git a/CMakeLists.txt b/CMakeLists.txt index be1ab50..799b278 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ endif() project(dlopen_test CXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -g -O0") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined") I don't get the same problem with Fedora.v Better results wiith "valgrind --leak-check=full --keep-debuginfo=yes ./build/dlopen_test" ==6339== 8 bytes in 1 blocks are definitely lost in loss record 1 of 15 ==6339== at 0x48447A8: malloc (vg_replace_malloc.c:446) ==6339== by 0x96A0A35: gomp_malloc (alloc.c:38) ==6339== by 0x96B788F: gomp_init_num_threads (proc.c:91) ==6339== by 0x969F1BB: initialize_env (env.c:2218) ==6339== by 0x40045B6: call_init (dl-init.c:74) ==6339== by 0x40045B6: call_init (dl-init.c:26) ==6339== by 0x40046AC: _dl_init (dl-init.c:121) ==6339== by 0x40015C1: _dl_catch_exception (dl-catch.c:215) ==6339== by 0x400B4FB: dl_open_worker (dl-open.c:829) ==6339== by 0x4001522: _dl_catch_exception (dl-catch.c:241) ==6339== by 0x400B903: _dl_open (dl-open.c:905) ==6339== by 0x4CA3F13: dlopen_doit (dlopen.c:56) ==6339== by 0x4001522: _dl_catch_exception (dl-catch.c:241) ==6339== ==6339== 96 bytes in 1 blocks are definitely lost in loss record 10 of 15 ==6339== at 0x484BC13: calloc (vg_replace_malloc.c:1675) ==6339== by 0x96A0A6D: gomp_malloc_cleared (alloc.c:47) ==6339== by 0x969F100: add_initial_icv_to_list (env.c:2159) ==6339== by 0x969F1D7: initialize_env (env.c:2224) ==6339== by 0x40045B6: call_init (dl-init.c:74) ==6339== by 0x40045B6: call_init (dl-init.c:26) ==6339== by 0x40046AC: _dl_init (dl-init.c:121) ==6339== by 0x40015C1: _dl_catch_exception (dl-catch.c:215) ==6339== by 0x400B4FB: dl_open_worker (dl-open.c:829) ==6339== by 0x4001522: _dl_catch_exception (dl-catch.c:241) ==6339== by 0x400B903: _dl_open (dl-open.c:905) ==6339== by 0x4CA3F13: dlopen_doit (dlopen.c:56) ==6339== by 0x4001522: _dl_catch_exception (dl-catch.c:241)
This is an allocation in libgomp for storing CPU affinity sets. The difference seems to be that dlclose on Fedora does not unload libgomp.so.1: libQt6Core.so.6 is marked NODELETE because it has a STB_GNU_UNIQUE symbol, it depends on libgomp.so.1, so libgomp.so.1 will stay around after that dlclose, too. NODELETE markings are logged by sufficiently new versions of glibc: LD_DEBUG=all build/dlopen_test </dev/null |& grep NODELETE You could report this as a GCC bug because libgomp could have an ELF destructor that frees the CPU set, or maybe a valgrind suppression file. Or maybe this allocation can be removed altogether because using a single global object as a scratch space does not look very thread-safe.
Thanks for the quick answers. From what you say readelf -h --dyn-syms /usr/lib/libQt6Core.so.6 | grep UNIQUE should give something on Fedora. I get nothing on Arch.
And indeed it does. 256 UNIQUE DEFAULT symbols.