Rust Memory leak

hi,
i was trying to write the fibonatchi code in rust and the result wasn't good.
here is code:
fn main() {
println!("{}", fib(47));
}

#[no_mangle]
fn fib(n: i64) -> i64 {
if n <= 1 { return n }
return fib(n - 1) + fib(n - 2)
}
and then i detected some memory leaks in the code(with valgrind).
look at this:
in use at exit: 205 bytes in 5 blocks
also you can see that just do valgrind ./rustcode.
and it is funy that c and cpp don't have memory leak with same code and even they are 4/5 sec faster than rust (with optimize and without optimize.
as we know rust , rust is safe and fast programming language but why in this code it is slower and even has memory leak?

even they are 4/5 sec faster than rust (with optimize and without optimize.

Recursion is not a good idea for something like this in Rust, because it can overflow the stack. This is also why it's slow.

I suggest reading Criterion's Getting Started Guide, as it has a good tutorial benchmarking the fibonnacci function.

As for the memory leak, I'm not sure.

2 Likes

yes speed wasn't matter for me my focus is on memory leak.
but it's good to say that also c and cpp can have good algorithm and we are comparing them in the same code

Go down a few lines further and you'll likely find that they're "still reachable", and not really a leak at all. It's not unusual. Programs with any sort of trivially destructible globals (or whatever the Rust terminology is) don't necessarily have to clean them up at program end. They could, if they wanted, but the end effect would be null and moot - it's literally just deallocating memory that's deallocated on process exit anyway. These allocations still exist, but the code still has a handle on them. It's when things are lost that you worry, because those probably would add up over time/iterations as there's clearly no mechanism to clean them.

Although from your code I got the following with rustc 1.51.0 (2fd73fabe 2021-03-23).

==1456== HEAP SUMMARY:
==1456==     in use at exit: 0 bytes in 0 blocks
==1456==   total heap usage: 12 allocs, 12 frees, 3,169 bytes allocated
==1456== 
==1456== All heap blocks were freed -- no leaks are possible

:man_shrugging:

edit: valgrind FAQ 4.1 kinda addresses this Valgrind (tl;dr if your allocator is doing clever laziness this is normal)

2 Likes

so i should call it good feature or bad?

What does "it" means? The absence of the memory leaks? If it can be called as feature, I can't imagine the case it would be considered bad.

The code in question does not make any memory allocations:

fn main() {
    println!("{}", fib(47));
}

#[no_mangle]
    fn fib(n: i64) -> i64 {
        if n <= 1 { return n }
        return fib(n - 1) + fib(n - 2)
}

So what is to leak?

Except I have no idea what goes on in println.

A few years ago I wanted to run a compiler for the Spin language in the web browser. No problem I thought, that compiler is written in C++ and I can compile it to asm.js with Emscripten. All worked well except every time it was run in a browser it used a ton more memory.

Turned out of course that that compiler did not deallocate a ton of objects when it exited. I mean why bother, the OS will do that.

Luckily the author understood what I wanted to do and fixed it by cleaning up properly.

In short, I don't think there should be any allocated memory hanging around when main has returned.

For what it's worth, printing to stdout often involves allocating a write buffer that lives forever. It might not even come from Rust, it might very well be libc (I know that glibc on Linux definitely does that), or at least something inbetween the language runtime and the write syscall.

2 Likes

Yes, Stdout is buffered.

Something you might want to test to determine whether it's a memory leak or some constant buffer allocated at some point is to just try larger inputs. If it's a bigger number we have a problem, because that would mean the "leak" comes from fib. If it remains at 205b then... that's a small penalty to pay for I guess? Otherwise you could elect to use non-buffered output offered in a separate crate.

2 Likes