Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory leak with "use" statement #252

Open
polnio opened this issue Jan 6, 2025 · 11 comments
Open

Memory leak with "use" statement #252

polnio opened this issue Jan 6, 2025 · 11 comments

Comments

@polnio
Copy link

polnio commented Jan 6, 2025

The issue

When I import anything from this crate, valgrind detect a memory leak, even if I'm not using what I'm importing, and even in release mode.

Node that when I encountered it the first time, it was on a bigger project, and valgrind didn't print the same output even with the same code: instead of 9,956 bytes still reachable, I had 137 bytes possibly lost, and it was related to tiny-xlib (but I don't have the issue when I import tiny-xlib in my code). Maybe it's due to other dependencies, even if they aren't included in my code... It's still quite strange.

Additional informations

softbuffer version : 0.4.6
Rust version : 1.82.0
Valgrind version : 3.23.0

Example 1: no memory leak

fn main() {}

Valgrind output:

valgrind ./target/debug/use-ml
==156047== Memcheck, a memory error detector
==156047== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==156047== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==156047== Command: ./target/debug/use-ml
==156047== 
==156047== 
==156047== HEAP SUMMARY:
==156047==     in use at exit: 0 bytes in 0 blocks
==156047==   total heap usage: 9 allocs, 9 frees, 2,160 bytes allocated
==156047== 
==156047== All heap blocks were freed -- no leaks are possible
==156047== 
==156047== For lists of detected and suppressed errors, rerun with: -s
==156047== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Example 2: memory leak

use softbuffer::Rect; // Or anything else from this crate

fn main() {}

Valgrind output:

valgrind ./target/debug/use-ml
==156550== Memcheck, a memory error detector
==156550== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==156550== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==156550== Command: ./target/debug/use-ml
==156550== 
==156550== 
==156550== HEAP SUMMARY:
==156550==     in use at exit: 9,956 bytes in 26 blocks
==156550==   total heap usage: 64 allocs, 38 frees, 18,968 bytes allocated
==156550== 
==156550== LEAK SUMMARY:
==156550==    definitely lost: 0 bytes in 0 blocks
==156550==    indirectly lost: 0 bytes in 0 blocks
==156550==      possibly lost: 0 bytes in 0 blocks
==156550==    still reachable: 9,956 bytes in 26 blocks
==156550==         suppressed: 0 bytes in 0 blocks
==156550== Rerun with --leak-check=full to see details of leaked memory
==156550== 
==156550== For lists of detected and suppressed errors, rerun with: -s
==156550== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Valgrind full output:

valgrind --leak-check=full --show-leak-kinds=all ./target/debug/use-ml
==157978== Memcheck, a memory error detector
==157978== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==157978== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==157978== Command: ./target/debug/use-ml
==157978== Parent PID: 75583
==157978== 
==157978== 
==157978== HEAP SUMMARY:
==157978==     in use at exit: 9,956 bytes in 26 blocks
==157978==   total heap usage: 64 allocs, 38 frees, 18,968 bytes allocated
==157978== 
==157978== 56 bytes in 2 blocks are still reachable in loss record 1 of 8
==157978==    at 0x48467D9: malloc (in /nix/store/jlcmn1sc1k1ryzk2lzxs3af4m1ghmdy6-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==157978==    by 0x4005A7B: decompose_rpath (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4007F3E: _dl_map_object (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40028B4: openaux (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4002C61: _dl_map_object_deps (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B940: dl_open_worker_begin (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B069: dl_open_worker (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B45B: _dl_open (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x490E78B: dlopen_doit (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/libc.so.6)
==157978== 
==157978== 152 bytes in 2 blocks are still reachable in loss record 2 of 8
==157978==    at 0x48467D9: malloc (in /nix/store/jlcmn1sc1k1ryzk2lzxs3af4m1ghmdy6-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==157978==    by 0x4026A8E: strdup (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4007CB9: _dl_map_object (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B8D8: dl_open_worker_begin (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B069: dl_open_worker (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B45B: _dl_open (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x490E78B: dlopen_doit (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/libc.so.6)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4001622: _dl_catch_error (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x490E206: _dlerror_run (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/libc.so.6)
==157978== 
==157978== 152 bytes in 2 blocks are still reachable in loss record 3 of 8
==157978==    at 0x48467D9: malloc (in /nix/store/jlcmn1sc1k1ryzk2lzxs3af4m1ghmdy6-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==157978==    by 0x400ADD0: _dl_new_object (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400633E: _dl_map_object_from_fd (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4007D40: _dl_map_object (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B8D8: dl_open_worker_begin (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B069: dl_open_worker (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B45B: _dl_open (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x490E78B: dlopen_doit (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/libc.so.6)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4001622: _dl_catch_error (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978== 
==157978== 303 bytes in 4 blocks are still reachable in loss record 4 of 8
==157978==    at 0x48467D9: malloc (in /nix/store/jlcmn1sc1k1ryzk2lzxs3af4m1ghmdy6-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==157978==    by 0x4004D86: open_path (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4008123: _dl_map_object (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40028B4: openaux (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4002C61: _dl_map_object_deps (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B940: dl_open_worker_begin (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B069: dl_open_worker (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B45B: _dl_open (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x490E78B: dlopen_doit (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/libc.so.6)
==157978== 
==157978== 303 bytes in 4 blocks are still reachable in loss record 5 of 8
==157978==    at 0x48467D9: malloc (in /nix/store/jlcmn1sc1k1ryzk2lzxs3af4m1ghmdy6-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==157978==    by 0x400ADD0: _dl_new_object (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400633E: _dl_map_object_from_fd (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4007D40: _dl_map_object (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40028B4: openaux (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4002C61: _dl_map_object_deps (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B940: dl_open_worker_begin (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B069: dl_open_worker (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B45B: _dl_open (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978== 
==157978== 1,344 bytes in 6 blocks are still reachable in loss record 6 of 8
==157978==    at 0x484E27A: calloc (in /nix/store/jlcmn1sc1k1ryzk2lzxs3af4m1ghmdy6-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==157978==    by 0x401313B: _dl_check_map_versions (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B982: dl_open_worker_begin (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B069: dl_open_worker (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B45B: _dl_open (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x490E78B: dlopen_doit (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/libc.so.6)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4001622: _dl_catch_error (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x490E206: _dlerror_run (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/libc.so.6)
==157978==    by 0x490E860: dlopen@@GLIBC_2.34 (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/libc.so.6)
==157978== 
==157978== 2,632 bytes in 2 blocks are still reachable in loss record 7 of 8
==157978==    at 0x484E27A: calloc (in /nix/store/jlcmn1sc1k1ryzk2lzxs3af4m1ghmdy6-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==157978==    by 0x400AAED: _dl_new_object (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400633E: _dl_map_object_from_fd (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4007D40: _dl_map_object (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B8D8: dl_open_worker_begin (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B069: dl_open_worker (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B45B: _dl_open (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x490E78B: dlopen_doit (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/libc.so.6)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4001622: _dl_catch_error (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978== 
==157978== 5,014 bytes in 4 blocks are still reachable in loss record 8 of 8
==157978==    at 0x484E27A: calloc (in /nix/store/jlcmn1sc1k1ryzk2lzxs3af4m1ghmdy6-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==157978==    by 0x400AAED: _dl_new_object (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400633E: _dl_map_object_from_fd (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4007D40: _dl_map_object (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40028B4: openaux (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x4002C61: _dl_map_object_deps (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B940: dl_open_worker_begin (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B069: dl_open_worker (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x40014F0: _dl_catch_exception (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978==    by 0x400B45B: _dl_open (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/ld-linux-x86-64.so.2)
==157978== 
==157978== LEAK SUMMARY:
==157978==    definitely lost: 0 bytes in 0 blocks
==157978==    indirectly lost: 0 bytes in 0 blocks
==157978==      possibly lost: 0 bytes in 0 blocks
==157978==    still reachable: 9,956 bytes in 26 blocks
==157978==         suppressed: 0 bytes in 0 blocks
==157978== 
==157978== For lists of detected and suppressed errors, rerun with: -s
==157978== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
@notgull
Copy link
Member

notgull commented Jan 6, 2025

What platform are you using?

@polnio
Copy link
Author

polnio commented Jan 7, 2025

Oh sorry, I forgot to mention it. I'm on Linux, on NixOS (on the nixos-unstable branch, updated a few days ago).

@madsmtm
Copy link
Member

madsmtm commented Jan 7, 2025

I strongly suspect that it's not an issue in softbuffer, could you try to do the same with our Linux dependencies:

# Cargo.toml
as-raw-xcb-connection = "1.0.0"
bytemuck = "1.12.3"
drm = { version = "0.14.1", default-features = false }
fastrand = "2.0.0"
memmap2 = "0.9.0"
rustix = { version = "0.38.19", features = [
    "fs",
    "mm",
    "shm",
    "std",
], default-features = false }
tiny-xlib = "0.2.1"
wayland-backend = { version = "0.3.0", features = [
    "client_system",
] }
wayland-client = "0.31.0"
wayland-sys = "0.31.0"
x11rb = { version = "0.13.0", features = [
    "allow-unsafe-code",
    "shm",
] }

And test a use krate as _; stmt separately for each of these.

@Ralith
Copy link

Ralith commented Jan 8, 2025

From the full output, everything seems to be rooted in dlopen. I'd investigate what's calling dlopen (using a debugger), and also why it's not also calling dlclose.

@kchibisov
Copy link
Member

Just strace it really, shouldn't be that hard to figure from this, since you'll see what gets loaded with dlopen.

@Ralith
Copy link

Ralith commented Jan 8, 2025

strace may not be sufficient to determine what's doing the loading, which (considering the no-op example) is I think the greater mystery here.

@kchibisov
Copy link
Member

kchibisov commented Jan 8, 2025

idk, strace was more than enough. It's done by tiny-xlib here https://github.com/notgull/tiny-xlib/blob/main/src/lib.rs#L150 due to use of ctor, since it tries to inject code to be run right on the start. The dlopen feature is what triggers all of that. Then the library is just not unloaded and thus the leak is present, since the lifetime is static.

Tbf, this is not a big of a deal, I'd say, and the use, just makes the crate used, thus triggers some code to be generated and injection triggered, since it's compile time.

@polnio
Copy link
Author

polnio commented Jan 8, 2025

I strongly suspect that it's not an issue in softbuffer, could you try to do the same with our Linux dependencies:

# Cargo.toml
as-raw-xcb-connection = "1.0.0"
bytemuck = "1.12.3"
drm = { version = "0.14.1", default-features = false }
fastrand = "2.0.0"
memmap2 = "0.9.0"
rustix = { version = "0.38.19", features = [
    "fs",
    "mm",
    "shm",
    "std",
], default-features = false }
tiny-xlib = "0.2.1"
wayland-backend = { version = "0.3.0", features = [
    "client_system",
] }
wayland-client = "0.31.0"
wayland-sys = "0.31.0"
x11rb = { version = "0.13.0", features = [
    "allow-unsafe-code",
    "shm",
] }

And test a use krate as _; stmt separately for each of these.

I tried what you said, and I don't have any memory leak. I just have more heap usage.

==13880== Memcheck, a memory error detector
==13880== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==13880== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==13880== Command: ./target/debug/use-ml
==13880== 
==13880== 
==13880== HEAP SUMMARY:
==13880==     in use at exit: 0 bytes in 0 blocks
==13880==   total heap usage: 12 allocs, 12 frees, 2,280 bytes allocated
==13880== 
==13880== All heap blocks were freed -- no leaks are possible
==13880== 
==13880== For lists of detected and suppressed errors, rerun with: -s
==13880== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

However I discovered something: with nix we can specify Linux build dependencies per project, and like a fool I didn't used the same Linux dependencies in my project and in my example. In my example I used "wayland" and "xorg.libX11", but if I replace the last one with "libxkbcommon" the results are differents.

use softbuffer as _;

fn main() {}
[package]
name = "use-ml"
version = "0.1.0"
edition = "2021"

[dependencies]
softbuffer = "0.4.6"

Short output:

==29215== Memcheck, a memory error detector
==29215== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==29215== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==29215== Command: ./target/debug/use-ml
==29215== 
==29215== 
==29215== HEAP SUMMARY:
==29215==     in use at exit: 137 bytes in 3 blocks
==29215==   total heap usage: 24 allocs, 21 frees, 2,769 bytes allocated
==29215== 
==29215== LEAK SUMMARY:
==29215==    definitely lost: 0 bytes in 0 blocks
==29215==    indirectly lost: 0 bytes in 0 blocks
==29215==      possibly lost: 137 bytes in 3 blocks
==29215==    still reachable: 0 bytes in 0 blocks
==29215==         suppressed: 0 bytes in 0 blocks
==29215== Rerun with --leak-check=full to see details of leaked memory
==29215== 
==29215== For lists of detected and suppressed errors, rerun with: -s
==29215== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Long output:

==29831== Memcheck, a memory error detector
==29831== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==29831== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==29831== Command: ./target/debug/use-ml
==29831== Parent PID: 4047
==29831== 
==29831== 
==29831== HEAP SUMMARY:
==29831==     in use at exit: 137 bytes in 3 blocks
==29831==   total heap usage: 24 allocs, 21 frees, 2,769 bytes allocated
==29831== 
==29831== 24 bytes in 1 blocks are possibly lost in loss record 1 of 3
==29831==    at 0x48467D9: malloc (in /nix/store/jlcmn1sc1k1ryzk2lzxs3af4m1ghmdy6-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==29831==    by 0x12518A: alloc::alloc::alloc (alloc.rs:98)
==29831==    by 0x1252D0: alloc::alloc::Global::alloc_impl (alloc.rs:181)
==29831==    by 0x1250C0: allocate (alloc.rs:241)
==29831==    by 0x1250C0: alloc::alloc::exchange_malloc (alloc.rs:330)
==29831==    by 0x1266D3: new<alloc::boxed::{impl#84}::from::StringError> (boxed.rs:257)
==29831==    by 0x1266D3: <alloc::boxed::Box<dyn core::error::Error+core::marker::Sync+core::marker::Send> as core::convert::From<alloc::string::String>>::from (boxed.rs:2675)
==29831==    by 0x1273E5: <T as core::convert::Into<U>>::into (mod.rs:759)
==29831==    by 0x126754: std::io::error::Error::new (error.rs:552)
==29831==    by 0x126042: tiny_xlib::_::_::init_storage::load_xlib_with_error_hook::error (lib.rs:168)
==29831==    by 0x12691D: core::ops::function::FnOnce::call_once (function.rs:250)
==29831==    by 0x125042: core::result::Result<T,E>::map_err (result.rs:854)
==29831==    by 0x125DA3: tiny_xlib::_::_::init_storage::load_xlib_with_error_hook (lib.rs:170)
==29831==    by 0x125CC5: tiny_xlib::_::_::init_storage (lib.rs:195)
==29831== 
==29831== 24 bytes in 1 blocks are possibly lost in loss record 2 of 3
==29831==    at 0x48467D9: malloc (in /nix/store/jlcmn1sc1k1ryzk2lzxs3af4m1ghmdy6-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==29831==    by 0x12C3AC: std::io::error::Error::_new (in /home/polnio/Documents/prog/test/rust/use-ml/target/debug/use-ml)
==29831==    by 0x126764: std::io::error::Error::new (error.rs:552)
==29831==    by 0x126042: tiny_xlib::_::_::init_storage::load_xlib_with_error_hook::error (lib.rs:168)
==29831==    by 0x12691D: core::ops::function::FnOnce::call_once (function.rs:250)
==29831==    by 0x125042: core::result::Result<T,E>::map_err (result.rs:854)
==29831==    by 0x125DA3: tiny_xlib::_::_::init_storage::load_xlib_with_error_hook (lib.rs:170)
==29831==    by 0x125CC5: tiny_xlib::_::_::init_storage (lib.rs:195)
==29831==    by 0x126095: tiny_xlib::_::_::__rust_ctor_lite__ctor::ctor (lib.rs:272)
==29831==    by 0x48AC3AD: __libc_start_main@@GLIBC_2.34 (in /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/libc.so.6)
==29831==    by 0x121E44: (below main) (in /home/polnio/Documents/prog/test/rust/use-ml/target/debug/use-ml)
==29831== 
==29831== 89 bytes in 1 blocks are possibly lost in loss record 3 of 3
==29831==    at 0x484E492: realloc (in /nix/store/jlcmn1sc1k1ryzk2lzxs3af4m1ghmdy6-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==29831==    by 0x168571: alloc::raw_vec::finish_grow (in /home/polnio/Documents/prog/test/rust/use-ml/target/debug/use-ml)
==29831==    by 0x1684FE: alloc::raw_vec::RawVecInner<A>::reserve::do_reserve_and_handle (in /home/polnio/Documents/prog/test/rust/use-ml/target/debug/use-ml)
==29831==    by 0x16881D: <alloc::string::String as core::fmt::Write>::write_str (in /home/polnio/Documents/prog/test/rust/use-ml/target/debug/use-ml)
==29831==    by 0x12B017: fmt<str> (mod.rs:2382)
==29831==    by 0x12B017: <alloc::borrow::Cow<B> as core::fmt::Display>::fmt (borrow.rs:405)
==29831==    by 0x16BF4A: core::fmt::write (in /home/polnio/Documents/prog/test/rust/use-ml/target/debug/use-ml)
==29831==    by 0x1291F9: core::fmt::Formatter::write_fmt (mod.rs:1658)
==29831==    by 0x12BE71: <libloading::error::Error as core::fmt::Display>::fmt (error.rs:113)
==29831==    by 0x16BF4A: core::fmt::write (in /home/polnio/Documents/prog/test/rust/use-ml/target/debug/use-ml)
==29831==    by 0x16873A: alloc::fmt::format::format_inner (in /home/polnio/Documents/prog/test/rust/use-ml/target/debug/use-ml)
==29831==    by 0x12A30F: alloc::fmt::format::{{closure}} (fmt.rs:642)
==29831==    by 0x129D5D: core::option::Option<T>::map_or_else (option.rs:1211)
==29831== 
==29831== LEAK SUMMARY:
==29831==    definitely lost: 0 bytes in 0 blocks
==29831==    indirectly lost: 0 bytes in 0 blocks
==29831==      possibly lost: 137 bytes in 3 blocks
==29831==    still reachable: 0 bytes in 0 blocks
==29831==         suppressed: 0 bytes in 0 blocks
==29831== 
==29831== For lists of detected and suppressed errors, rerun with: -s
==29831== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

But again with your example I don't have memory leak. Note that libxkbcommon wasn't enough, I had to add libX11, so I think it's related to libxkbcommon. Morover when I put libX11 AND libxkbcommon in the Linux dependencies, and I have the output I had without libxkbcommon (so my second example, in my first message)

I think there is something between the rust dependency "tiny-xlib" and the Linux dependency "libxkbcommon", however it doesn't happen when I import "tiny-xlib" without "softbuffer"

@kchibisov
Copy link
Member

kchibisov commented Jan 8, 2025

@polnio I've already debugged your issue, so don't waste your time. See #252 (comment)

@polnio
Copy link
Author

polnio commented Jan 8, 2025

Yes, but it seems that it's not just about tiny-xlib, because like I said it doesn't happen when I import this crate instead of softbuffer

@kchibisov
Copy link
Member

@polnio it doesn't matter, the point is that it's done by ctor and runtime loading, you can search other creates for doing the same, since rust runtime is the only thing that is being run for you.

Other crates could do so as well, in the softbuffer case, you can clearly see in strace what is being loaded, you can do the same with other crates.

It doesn't happen when you import this crate, because you don't enable libloading feature in it, since by default it does normal linking and ctor code is only being run when you have said feature, which is not a default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

5 participants