From what I can gather, it appears that when C code (and possibly anything else) is calling into rust code, the rust code will never have its cleanup routines run. This results in things like io::stdio::stdout()
(and possibly a bunch of other things) allocating space and setting up resources that are never freed and torn down, respectively. Given that this has to do with the fact that rust isn't actually the main executable with a single entry point, it seems that this task of calling the cleanup has to be done from C. Is there a good way to do that?
#![crate_type = "staticlib"]
#[no_mangle]
pub extern fn double_input(input: i32) -> i32 {
println!("{} {}", "hello world: ", input);
input * 2
}
$ rustc --version
rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)
$ valgrind --leak-check=full --show-leak-kinds=all ./target/double
==15247== Memcheck, a memory error detector
==15247== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==15247== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==15247== Command: ./target/double
==15247==
hello world: 4
4 * 2 = 8
==15247==
==15247== HEAP SUMMARY:
==15247== in use at exit: 1,288 bytes in 8 blocks
==15247== total heap usage: 9 allocs, 1 frees, 1,320 bytes allocated
==15247==
==15247== 8 bytes in 1 blocks are still reachable in loss record 1 of 8
==15247== at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x404127: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247== by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==
==15247== 8 bytes in 1 blocks are still reachable in loss record 2 of 8
==15247== at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x404A0D: io::stdio::stdout::stdout_init::hf0a88977d03b8f3f3Mg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x40415A: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247== by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==
==15247== 8 bytes in 1 blocks are still reachable in loss record 3 of 8
==15247== at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x40417C: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247== by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==
==15247== 32 bytes in 1 blocks are still reachable in loss record 4 of 8
==15247== at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x403F3B: rt::at_exit_imp::push::h8b92b68766e7993dZiw (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x40414E: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247== by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==
==15247== 48 bytes in 1 blocks are still reachable in loss record 5 of 8
==15247== at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x404BD7: sys::mutex::ReentrantMutex::new::h9030e93b64febd67dzt (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x404A1E: io::stdio::stdout::stdout_init::hf0a88977d03b8f3f3Mg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x40415A: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247== by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==
==15247== 64 bytes in 1 blocks are still reachable in loss record 6 of 8
==15247== at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x409815: vec::Vec$LT$T$GT$::push::resize::h13970319319561877210 (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x403F80: rt::at_exit_imp::push::h8b92b68766e7993dZiw (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x40414E: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247== by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==
==15247== 96 bytes in 1 blocks are still reachable in loss record 7 of 8
==15247== at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x404A8B: io::stdio::stdout::stdout_init::hf0a88977d03b8f3f3Mg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x40415A: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247== by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==
==15247== 1,024 bytes in 1 blocks are still reachable in loss record 8 of 8
==15247== at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x404923: io::stdio::stdout::stdout_init::hf0a88977d03b8f3f3Mg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x40415A: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247== by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==
==15247== LEAK SUMMARY:
==15247== definitely lost: 0 bytes in 0 blocks
==15247== indirectly lost: 0 bytes in 0 blocks
==15247== possibly lost: 0 bytes in 0 blocks
==15247== still reachable: 1,288 bytes in 8 blocks
==15247== suppressed: 0 bytes in 0 blocks
==15247==
==15247== For counts of detected and suppressed errors, rerun with: -v
==15247== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)