Memery leak with `std::thread::scope`?

⚓ Rust    📅 2025-10-27    👤 surdeus    👁️ 3      

surdeus

Hello,
I have the following snippet

fn main() {
    std::thread::scope(|scope| {
        let t1 = scope.spawn(|| {});
        t1.join().unwrap();
    });
}

Running the program within Valgrind gives the following errors

==1267185== Memcheck, a memory error detector
==1267185== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==1267185== Using Valgrind-3.25.1 and LibVEX; rerun with -h for copyright info
==1267185== Command: target/debug/threadscope
==1267185==
==1267185==
==1267185== HEAP SUMMARY:
==1267185==     in use at exit: 504 bytes in 2 blocks
==1267185==   total heap usage: 9,012 allocs, 9,010 frees, 466,916 bytes allocated
==1267185==
==1267185== 48 bytes in 1 blocks are possibly lost in loss record 1 of 2
==1267185==    at 0x48A8866: malloc (vg_replace_malloc.c:446)
==1267185==    by 0x4026E43: alloc (alloc.rs:94)
==1267185==    by 0x4026E43: alloc_impl (alloc.rs:189)
==1267185==    by 0x4026E43: allocate (alloc.rs:250)
==1267185==    by 0x4026E43: {closure#0}<std::thread::Inner> (sync.rs:505)
==1267185==    by 0x4026E43: allocate_for_layout<core::mem::maybe_uninit::MaybeUninit<std::thread::Inner>, alloc::sync::{impl#14}::new_uninit::{closure_env#0}<std::thread::Inner>, fn(*mut u8) -> *mut alloc::sync::ArcInner<core::mem::maybe_uninit::MaybeUninit<std::thread::Inner>>> (sync.rs:1985)
==1267185==    by 0x4026E43: new_uninit<std::thread::Inner> (sync.rs:503)
==1267185==    by 0x4026E43: std::thread::Thread::new (mod.rs:1429)
==1267185==    by 0x40053AF: std::thread::current::init_current (current.rs:227)
==1267185==    by 0x4007890: std::thread::scoped::scope (scoped.rs:143)
==1267185==    by 0x400D701: threadscope::main (main.rs:3)
==1267185==    by 0x400A37A: core::ops::function::FnOnce::call_once (function.rs:250)
==1267185==    by 0x40089ED: std::sys::backtrace::__rust_begin_short_backtrace (backtrace.rs:152)
==1267185==    by 0x4007720: std::rt::lang_start::{{closure}} (rt.rs:206)
==1267185==    by 0x402621F: call_once<(), (dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (function.rs:284)
==1267185==    by 0x402621F: do_call<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panicking.rs:589)
==1267185==    by 0x402621F: catch_unwind<i32, &(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (panicking.rs:552)
==1267185==    by 0x402621F: catch_unwind<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panic.rs:359)
==1267185==    by 0x402621F: {closure#0} (rt.rs:175)
==1267185==    by 0x402621F: do_call<std::rt::lang_start_internal::{closure_env#0}, isize> (panicking.rs:589)
==1267185==    by 0x402621F: catch_unwind<isize, std::rt::lang_start_internal::{closure_env#0}> (panicking.rs:552)
==1267185==    by 0x402621F: catch_unwind<std::rt::lang_start_internal::{closure_env#0}, isize> (panic.rs:359)
==1267185==    by 0x402621F: std::rt::lang_start_internal (rt.rs:171)
==1267185==    by 0x4007706: std::rt::lang_start (rt.rs:205)
==1267185==    by 0x400D72D: main (in /home/antlord/Nest/personal/threadscope/target/debug/threadscope)
==1267185==
==1267185== LEAK SUMMARY:
==1267185==    definitely lost: 0 bytes in 0 blocks
==1267185==    indirectly lost: 0 bytes in 0 blocks
==1267185==      possibly lost: 48 bytes in 1 blocks
==1267185==    still reachable: 456 bytes in 1 blocks
==1267185==         suppressed: 0 bytes in 0 blocks
==1267185== Reachable blocks (those to which a pointer was found) are not shown.
==1267185== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==1267185==
==1267185== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Do I misuse std::thread::scope? I don't get errors if I use std::thread::spawn itself. Also, the values of memory in "possibly lost" and "still reachable" don't grow if I run std::thread::scope in a loop with thousands of iterations.

Just in case here is the environment:
rustc --version: rustc 1.89.0 (29483883e 2025-08-04)
OS: Linux 6.15.10-100.fc41.x86_64 (Fedora 41)

Offtopic: how do I disable the emoji in the topic title? Other people might not find the thread because of it.

3 posts - 3 participants

Read full topic

🏷️ Rust_feed