Skip to content

Fix Memory Leak in Client Initialization#834

Open
GeorgeBerdovskiy wants to merge 2 commits into
fede1024:masterfrom
GeorgeBerdovskiy:george/fix-native-config-memory-leak
Open

Fix Memory Leak in Client Initialization#834
GeorgeBerdovskiy wants to merge 2 commits into
fede1024:masterfrom
GeorgeBerdovskiy:george/fix-native-config-memory-leak

Conversation

@GeorgeBerdovskiy
Copy link
Copy Markdown

In src/client.rs, the C function rd_kafka_new is called with a pointer to a NativeClientConfig object. According to a comment in the implementation of rd_kafka_new, it takes ownership of the config on success. That means when the function fails, the caller is responsible for freeing it. See line 2445 of src/rdkafka.c in the librdkafka repository.

By calling ManuallyDrop::new(native_config), the Rust client initialization code prevents the compiler from dropping the config automatically. Otherwise, it would be dropped even though rd_kafka_new took ownership of it, resulting in possible UAF bugs.

Because of this, when rd_kafka_new fails, the config isn't dropped, resulting in a memory leak. I confirmed this using a simple Rust program and Valgrind.

Code

use rdkafka::config::ClientConfig;
use rdkafka::client::{DefaultClientContext, Client};

use rdkafka_sys::RDKafkaType;

fn main() {
    println!("Starting memory leak reproduction...");

    let mut binding = ClientConfig::new();
    let config = binding
        .set("acks", "1")
        .set("enable.idempotence", "true");

    let native_config = config.create_native_config().unwrap();

    let err = Client::new(
        &config,
        native_config,
        RDKafkaType::RD_KAFKA_PRODUCER,
        DefaultClientContext,
    );

    if err.is_err() {
        println!("Client creation errored out as expected");
    }
}

Command

valgrind --leak-check=full --show-leak-kinds=all \
  target/debug/memory-leak-repro  --test-threads=1

Output

==16317== Memcheck, a memory error detector
==16317== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==16317== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==16317== Command: target/debug/memory-leak-repro --test-threads=1
==16317==
Starting memory leak reproduction...
Client creation errored out as expected
==16317==
==16317== HEAP SUMMARY:
==16317==     in use at exit: 3,386 bytes in 18 blocks
==16317==   total heap usage: 40 allocs, 22 frees, 6,840 bytes allocated
==16317==
==16317== 7 bytes in 1 blocks are indirectly lost in loss record 1 of 7
==16317==    at 0x4885250: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-arm64-linux.so)
==16317==    by 0x4A4D62F: strdup (strdup.c:42)
==16317==    by 0x161473: rd_strdup (rd.h:158)
==16317==    by 0x161473: rd_kafka_anyconf_set_prop0 (???:1995)
==16317==    by 0x15B297: rd_kafka_anyconf_set (rdkafka_conf.c:2509)
==16317==    by 0x15F0EB: rd_kafka_conf_set (rdkafka_conf.c:2551)
==16317==    by 0x15F0EB: rd_kafka_conf_finalize (???:4154)
==16317==    by 0x137A1F: rd_kafka_new (rdkafka.c:2341)
==16317==    by 0x12B22B: rdkafka::client::Client<C>::new_context_arc (client.rs:261)
==16317==    by 0x12B543: rdkafka::client::Client<C>::new (client.rs:240)
==16317==    by 0x1270B7: memory_leak_repro::main (main.rs:16)
==16317==    by 0x12618B: core::ops::function::FnOnce::call_once (library/core/src/ops/function.rs:250)
==16317==    by 0x1262E7: std::sys::backtrace::__rust_begin_short_backtrace (library/std/src/sys/backtrace.rs:166)
==16317==    by 0x125B53: std::rt::lang_start::{{closure}} (library/std/src/rt.rs:206)
==16317==
==16317== 20 bytes in 2 blocks are indirectly lost in loss record 2 of 7
==16317==    at 0x4885250: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-arm64-linux.so)
==16317==    by 0x4A4D62F: strdup (strdup.c:42)
==16317==    by 0x161473: rd_strdup (rd.h:158)
==16317==    by 0x161473: rd_kafka_anyconf_set_prop0 (???:1995)
==16317==    by 0x15AFE7: rd_kafka_defaultconf_set (rdkafka_conf.c:2441)
==16317==    by 0x15AFE7: rd_kafka_topic_conf_new (???:2461)
==16317==    by 0x15B10B: rd_kafka_conf_set (rdkafka_conf.c:2563)
==16317==    by 0x129173: rdkafka::config::NativeClientConfig::set (config.rs:174)
==16317==    by 0x128E1B: rdkafka::config::ClientConfig::create_native_config (config.rs:299)
==16317==    by 0x126FF7: memory_leak_repro::main (main.rs:14)
==16317==    by 0x12618B: core::ops::function::FnOnce::call_once (library/core/src/ops/function.rs:250)
==16317==    by 0x1262E7: std::sys::backtrace::__rust_begin_short_backtrace (library/std/src/sys/backtrace.rs:166)
==16317==    by 0x125B53: std::rt::lang_start::{{closure}} (library/std/src/rt.rs:206)
==16317==    by 0x2AAA53: call_once<(), (dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (function.rs:287)
==16317==    by 0x2AAA53: do_call<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panicking.rs:581)
==16317==    by 0x2AAA53: catch_unwind<i32, &(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (panicking.rs:544)
==16317==    by 0x2AAA53: catch_unwind<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panic.rs:359)
==16317==    by 0x2AAA53: {closure#0} (rt.rs:175)
==16317==    by 0x2AAA53: do_call<std::rt::lang_start_internal::{closure_env#0}, isize> (panicking.rs:581)
==16317==    by 0x2AAA53: catch_unwind<isize, std::rt::lang_start_internal::{closure_env#0}> (panicking.rs:544)
==16317==    by 0x2AAA53: catch_unwind<std::rt::lang_start_internal::{closure_env#0}, isize> (panic.rs:359)
==16317==    by 0x2AAA53: std::rt::lang_start_internal (rt.rs:171)
==16317==
==16317== 46 bytes in 2 blocks are indirectly lost in loss record 3 of 7
==16317==    at 0x4885250: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-arm64-linux.so)
==16317==    by 0x16140F: rd_malloc (rd.h:141)
==16317==    by 0x16140F: rd_kafkap_str_new (rdkafka_proto.h:315)
==16317==    by 0x16140F: rd_kafka_anyconf_set_prop0 (???:2006)
==16317==    by 0x15AEC3: rd_kafka_defaultconf_set (rdkafka_conf.c:2441)
==16317==    by 0x15AEC3: rd_kafka_conf_new (???:2452)
==16317==    by 0x128D13: rdkafka::config::ClientConfig::create_native_config (config.rs:297)
==16317==    by 0x126FF7: memory_leak_repro::main (main.rs:14)
==16317==    by 0x12618B: core::ops::function::FnOnce::call_once (library/core/src/ops/function.rs:250)
==16317==    by 0x1262E7: std::sys::backtrace::__rust_begin_short_backtrace (library/std/src/sys/backtrace.rs:166)
==16317==    by 0x125B53: std::rt::lang_start::{{closure}} (library/std/src/rt.rs:206)
==16317==    by 0x2AAA53: call_once<(), (dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (function.rs:287)
==16317==    by 0x2AAA53: do_call<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panicking.rs:581)
==16317==    by 0x2AAA53: catch_unwind<i32, &(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (panicking.rs:544)
==16317==    by 0x2AAA53: catch_unwind<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panic.rs:359)
==16317==    by 0x2AAA53: {closure#0} (rt.rs:175)
==16317==    by 0x2AAA53: do_call<std::rt::lang_start_internal::{closure_env#0}, isize> (panicking.rs:581)
==16317==    by 0x2AAA53: catch_unwind<isize, std::rt::lang_start_internal::{closure_env#0}> (panicking.rs:544)
==16317==    by 0x2AAA53: catch_unwind<std::rt::lang_start_internal::{closure_env#0}, isize> (panic.rs:359)
==16317==    by 0x2AAA53: std::rt::lang_start_internal (rt.rs:171)
==16317==    by 0x125B2B: std::rt::lang_start (library/std/src/rt.rs:205)
==16317==    by 0x127187: main (in /home/memory-leak-repro/target/debug/memory-leak-repro)
==16317==
==16317== 217 bytes in 10 blocks are indirectly lost in loss record 4 of 7
==16317==    at 0x4885250: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-arm64-linux.so)
==16317==    by 0x4A4D62F: strdup (strdup.c:42)
==16317==    by 0x161473: rd_strdup (rd.h:158)
==16317==    by 0x161473: rd_kafka_anyconf_set_prop0 (???:1995)
==16317==    by 0x15AEC3: rd_kafka_defaultconf_set (rdkafka_conf.c:2441)
==16317==    by 0x15AEC3: rd_kafka_conf_new (???:2452)
==16317==    by 0x128D13: rdkafka::config::ClientConfig::create_native_config (config.rs:297)
==16317==    by 0x126FF7: memory_leak_repro::main (main.rs:14)
==16317==    by 0x12618B: core::ops::function::FnOnce::call_once (library/core/src/ops/function.rs:250)
==16317==    by 0x1262E7: std::sys::backtrace::__rust_begin_short_backtrace (library/std/src/sys/backtrace.rs:166)
==16317==    by 0x125B53: std::rt::lang_start::{{closure}} (library/std/src/rt.rs:206)
==16317==    by 0x2AAA53: call_once<(), (dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (function.rs:287)
==16317==    by 0x2AAA53: do_call<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panicking.rs:581)
==16317==    by 0x2AAA53: catch_unwind<i32, &(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (panicking.rs:544)
==16317==    by 0x2AAA53: catch_unwind<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panic.rs:359)
==16317==    by 0x2AAA53: {closure#0} (rt.rs:175)
==16317==    by 0x2AAA53: do_call<std::rt::lang_start_internal::{closure_env#0}, isize> (panicking.rs:581)
==16317==    by 0x2AAA53: catch_unwind<isize, std::rt::lang_start_internal::{closure_env#0}> (panicking.rs:544)
==16317==    by 0x2AAA53: catch_unwind<std::rt::lang_start_internal::{closure_env#0}, isize> (panic.rs:359)
==16317==    by 0x2AAA53: std::rt::lang_start_internal (rt.rs:171)
==16317==    by 0x125B2B: std::rt::lang_start (library/std/src/rt.rs:205)
==16317==    by 0x127187: main (in /home/memory-leak-repro/target/debug/memory-leak-repro)
==16317==
==16317== 384 bytes in 1 blocks are indirectly lost in loss record 5 of 7
==16317==    at 0x488C0AC: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-arm64-linux.so)
==16317==    by 0x15AFAB: rd_calloc (rd.h:135)
==16317==    by 0x15AFAB: rd_kafka_topic_conf_new (???:2458)
==16317==    by 0x15B10B: rd_kafka_conf_set (rdkafka_conf.c:2563)
==16317==    by 0x129173: rdkafka::config::NativeClientConfig::set (config.rs:174)
==16317==    by 0x128E1B: rdkafka::config::ClientConfig::create_native_config (config.rs:299)
==16317==    by 0x126FF7: memory_leak_repro::main (main.rs:14)
==16317==    by 0x12618B: core::ops::function::FnOnce::call_once (library/core/src/ops/function.rs:250)
==16317==    by 0x1262E7: std::sys::backtrace::__rust_begin_short_backtrace (library/std/src/sys/backtrace.rs:166)
==16317==    by 0x125B53: std::rt::lang_start::{{closure}} (library/std/src/rt.rs:206)
==16317==    by 0x2AAA53: call_once<(), (dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (function.rs:287)
==16317==    by 0x2AAA53: do_call<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panicking.rs:581)
==16317==    by 0x2AAA53: catch_unwind<i32, &(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (panicking.rs:544)
==16317==    by 0x2AAA53: catch_unwind<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panic.rs:359)
==16317==    by 0x2AAA53: {closure#0} (rt.rs:175)
==16317==    by 0x2AAA53: do_call<std::rt::lang_start_internal::{closure_env#0}, isize> (panicking.rs:581)
==16317==    by 0x2AAA53: catch_unwind<isize, std::rt::lang_start_internal::{closure_env#0}> (panicking.rs:544)
==16317==    by 0x2AAA53: catch_unwind<std::rt::lang_start_internal::{closure_env#0}, isize> (panic.rs:359)
==16317==    by 0x2AAA53: std::rt::lang_start_internal (rt.rs:171)
==16317==    by 0x125B2B: std::rt::lang_start (library/std/src/rt.rs:205)
==16317==    by 0x127187: main (in /home/memory-leak-repro/target/debug/memory-leak-repro)
==16317==
==16317== 544 bytes in 1 blocks are still reachable in loss record 6 of 7
==16317==    at 0x4885250: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-arm64-linux.so)
==16317==    by 0x2ADACB: alloc (alloc.rs:95)
==16317==    by 0x2ADACB: alloc_impl_runtime (alloc.rs:190)
==16317==    by 0x2ADACB: alloc_impl (alloc.rs:312)
==16317==    by 0x2ADACB: allocate (alloc.rs:429)
==16317==    by 0x2ADACB: try_new_uninit_in<alloc::collections::btree::node::LeafNode<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo>, alloc::alloc::Global> (boxed.rs:614)
==16317==    by 0x2ADACB: new_uninit_in<alloc::collections::btree::node::LeafNode<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo>, alloc::alloc::Global> (boxed.rs:581)
==16317==    by 0x2ADACB: new<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo, alloc::alloc::Global> (node.rs:87)
==16317==    by 0x2ADACB: new_leaf<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo, alloc::alloc::Global> (node.rs:225)
==16317==    by 0x2ADACB: insert_entry<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo, alloc::alloc::Global> (entry.rs:403)
==16317==    by 0x2ADACB: insert<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo, alloc::alloc::Global> (entry.rs:377)
==16317==    by 0x2ADACB: insert<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo, alloc::alloc::Global> (map.rs:1053)
==16317==    by 0x2ADACB: std::sys::pal::unix::stack_overflow::thread_info::set_current_info (thread_info.rs:122)
==16317==    by 0x2AA98F: init (stack_overflow.rs:179)
==16317==    by 0x2AA98F: init (mod.rs:41)
==16317==    by 0x2AA98F: init (rt.rs:118)
==16317==    by 0x2AA98F: {closure#0} (rt.rs:173)
==16317==    by 0x2AA98F: do_call<std::rt::lang_start_internal::{closure_env#0}, isize> (panicking.rs:581)
==16317==    by 0x2AA98F: catch_unwind<isize, std::rt::lang_start_internal::{closure_env#0}> (panicking.rs:544)
==16317==    by 0x2AA98F: catch_unwind<std::rt::lang_start_internal::{closure_env#0}, isize> (panic.rs:359)
==16317==    by 0x2AA98F: std::rt::lang_start_internal (rt.rs:171)
==16317==    by 0x125B2B: std::rt::lang_start (library/std/src/rt.rs:205)
==16317==    by 0x127187: main (in /home/memory-leak-repro/target/debug/memory-leak-repro)
==16317==
==16317== 2,842 (2,168 direct, 674 indirect) bytes in 1 blocks are definitely lost in loss record 7 of 7
==16317==    at 0x488C0AC: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-arm64-linux.so)
==16317==    by 0x15AE87: rd_calloc (rd.h:135)
==16317==    by 0x15AE87: rd_kafka_conf_new (???:2449)
==16317==    by 0x128D13: rdkafka::config::ClientConfig::create_native_config (config.rs:297)
==16317==    by 0x126FF7: memory_leak_repro::main (main.rs:14)
==16317==    by 0x12618B: core::ops::function::FnOnce::call_once (library/core/src/ops/function.rs:250)
==16317==    by 0x1262E7: std::sys::backtrace::__rust_begin_short_backtrace (library/std/src/sys/backtrace.rs:166)
==16317==    by 0x125B53: std::rt::lang_start::{{closure}} (library/std/src/rt.rs:206)
==16317==    by 0x2AAA53: call_once<(), (dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (function.rs:287)
==16317==    by 0x2AAA53: do_call<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panicking.rs:581)
==16317==    by 0x2AAA53: catch_unwind<i32, &(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (panicking.rs:544)
==16317==    by 0x2AAA53: catch_unwind<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panic.rs:359)
==16317==    by 0x2AAA53: {closure#0} (rt.rs:175)
==16317==    by 0x2AAA53: do_call<std::rt::lang_start_internal::{closure_env#0}, isize> (panicking.rs:581)
==16317==    by 0x2AAA53: catch_unwind<isize, std::rt::lang_start_internal::{closure_env#0}> (panicking.rs:544)
==16317==    by 0x2AAA53: catch_unwind<std::rt::lang_start_internal::{closure_env#0}, isize> (panic.rs:359)
==16317==    by 0x2AAA53: std::rt::lang_start_internal (rt.rs:171)
==16317==    by 0x125B2B: std::rt::lang_start (library/std/src/rt.rs:205)
==16317==    by 0x127187: main (in /home/memory-leak-repro/target/debug/memory-leak-repro)
==16317==
==16317== LEAK SUMMARY:
==16317==    definitely lost: 2,168 bytes in 1 blocks
==16317==    indirectly lost: 674 bytes in 16 blocks
==16317==      possibly lost: 0 bytes in 0 blocks
==16317==    still reachable: 544 bytes in 1 blocks
==16317==         suppressed: 0 bytes in 0 blocks
==16317==
==16317== For lists of detected and suppressed errors, rerun with: -s
==16317== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

The fix is simple. If rd_kafka_new fails (returns a null pointer), let Rust drop the config automatically. If it succeeds (does NOT return a null pointer), forget the config.

Here's what Valgrind has to say for the same program using my fix.

==29721== Memcheck, a memory error detector
==29721== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==29721== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==29721== Command: target/debug/memory-leak-repro --test-threads=1
==29721==
==29721==
==29721== HEAP SUMMARY:
==29721==     in use at exit: 544 bytes in 1 blocks
==29721==   total heap usage: 30,010 allocs, 30,009 frees, 3,199,644 bytes allocated
==29721==
==29721== 544 bytes in 1 blocks are still reachable in loss record 1 of 1
==29721==    at 0x4885250: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-arm64-linux.so)
==29721==    by 0x2AE423: alloc (alloc.rs:95)
==29721==    by 0x2AE423: alloc_impl_runtime (alloc.rs:190)
==29721==    by 0x2AE423: alloc_impl (alloc.rs:312)
==29721==    by 0x2AE423: allocate (alloc.rs:429)
==29721==    by 0x2AE423: try_new_uninit_in<alloc::collections::btree::node::LeafNode<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo>, alloc::alloc::Global> (boxed.rs:614)
==29721==    by 0x2AE423: new_uninit_in<alloc::collections::btree::node::LeafNode<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo>, alloc::alloc::Global> (boxed.rs:581)
==29721==    by 0x2AE423: new<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo, alloc::alloc::Global> (node.rs:87)
==29721==    by 0x2AE423: new_leaf<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo, alloc::alloc::Global> (node.rs:225)
==29721==    by 0x2AE423: insert_entry<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo, alloc::alloc::Global> (entry.rs:403)
==29721==    by 0x2AE423: insert<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo, alloc::alloc::Global> (entry.rs:377)
==29721==    by 0x2AE423: insert<usize, std::sys::pal::unix::stack_overflow::thread_info::ThreadInfo, alloc::alloc::Global> (map.rs:1053)
==29721==    by 0x2AE423: std::sys::pal::unix::stack_overflow::thread_info::set_current_info (thread_info.rs:122)
==29721==    by 0x2AB2E7: init (stack_overflow.rs:179)
==29721==    by 0x2AB2E7: init (mod.rs:41)
==29721==    by 0x2AB2E7: init (rt.rs:118)
==29721==    by 0x2AB2E7: {closure#0} (rt.rs:173)
==29721==    by 0x2AB2E7: do_call<std::rt::lang_start_internal::{closure_env#0}, isize> (panicking.rs:581)
==29721==    by 0x2AB2E7: catch_unwind<isize, std::rt::lang_start_internal::{closure_env#0}> (panicking.rs:544)
==29721==    by 0x2AB2E7: catch_unwind<std::rt::lang_start_internal::{closure_env#0}, isize> (panic.rs:359)
==29721==    by 0x2AB2E7: std::rt::lang_start_internal (rt.rs:171)
==29721==    by 0x12632B: std::rt::lang_start (library/std/src/rt.rs:205)
==29721==    by 0x1261AB: main (in /home/memory-leak-repro/target/debug/memory-leak-repro)
==29721==
==29721== LEAK SUMMARY:
==29721==    definitely lost: 0 bytes in 0 blocks
==29721==    indirectly lost: 0 bytes in 0 blocks
==29721==      possibly lost: 0 bytes in 0 blocks
==29721==    still reachable: 544 bytes in 1 blocks
==29721==         suppressed: 0 bytes in 0 blocks
==29721==
==29721== For lists of detected and suppressed errors, rerun with: -s
==29721== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant