Lazy_static - How is memory freed?

How is data freed when using lazy_static? The documentation states that no destructors (drop-fn) are called when using lazy_static. I've also read somewhere that Rust doesn't allow any user defined code before or after main execution.

So what happens with any data allocated on the heap via lazy_static?
Does this mean that there is a memory leak and Rust doesn't free this memory by purpose? Or are there any special ways this is done? Or does the OS need to take care of this when the process ends?

The OS cleans up all allocations after the process exits. Note: anything stored in static will not be automatically dropped.

2 Likes

So to sum it up the behavior is different than in C++?
But could I do something like replacing the memory with something empty via std::mem::replace(...) to free the memory/to make the leak as small as possible in the end? Is this feasible?

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c811a57a6470f118b74ab8191ef445f5

I know in this example a global static variable is useless, but just to show my issue.

Yes

You already did it, it only uses safe code and it does what you expect it to do. Looks perfectly fine to me, what's the problem?

Unless the Drop implementation has side-effects like resetting the terminal from raw mode to the regular mode or removing temporary files, leaking at the end of the program is not a problem at all. Memory will be deallocated all at once by the OS when the program exits anyway. This OS deallocation is even faster than manual deallocation in the Drop implementation as it doesn't have the overhead of keeping the memory allocator state correct and recursively walking the memory to be dropped.

1 Like

Alright I get it, thanks for your answers!

Well what's the C++ equivalent? During the several years of C++ development I have done, I haven't come across anything like Rust's lazy_static! in C++. C++ has mutable-by-default statics with weird initialization order hazards, so you can use regular statics for dynamic initialization. Rust's statics, just like those of C++, don't allocate dynamically and don't leak it. However, lazy_static! "leaking" is not a problem because the allocated memory is supposed to live until the end of the program anyway.

I might not be aware of some lazy_static! features, but for simple one-off initialisation at runtime, the most common C++ way I've encountered is like

void foo()
{
    static const auto dataDir = readConfig("data-dir");
    ...
}

which doesn't suffer from the special cases of global static variables (especially when loading objects via dlopen()) since it's initialised only when the function is called. Plus it's much easier to reason about types, safety, etc. As far as I can tell, that's what lazy_static! is doing (except IIRC you can't use it inside functions?)

You can, it's just a static with a Deref impl. (Playground)

2 Likes

Strictly speaking, not mut, just static - that's why using it is not unsafe.

1 Like

Right, I amended my post.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.