There's also no guarantee for Rust/C++ destructors to be called. It's certainly less of an issue then depending on the GC to being called, but if you need absolute correctness, then you shouldn't rely on the destructors.
There's also no guarantee for Rust/C++ destructors to be called. It's certainly less of an issue then depending on the GC to being called, but if you need absolute correctness, then you shouldn't rely on the destructors.
If you allocate an object on the heap with `new` then its destructor isn't called automatically unless you make it so through some other mechanism, but GP comment clearly want claiming that.
There are some situations where objects with block scope do not have their destructor called e.g. `_exit()` called, segfault, power cable pulled out. But in that sense nothing is guaranteed.
The issue is when you produce an API that contains objects with destructors. Since you are handing these entities off to unknown code, you cannot ensure that they will be dropped. This was a problem in scoped threads in Rust.
In which case in rust you cannot be sure that "the drop" will be called?
See the very excellent http://cglab.ca/~abeinges/blah/everyone-poops/
But Rc would not work if the drop was not guaranteed to be called.
Not the parent, but it is trivial to write C++ and Rust examples in which destructors of variables with block scope are not called. The std library of both languages do even come with utilities to do this:
C++ structs:
struct Foo {
Foo() { std::cout << "Foo()" << std::endl; }
~Foo() { std::cout << "~Foo()" << std::endl; }
};
{
std::aligned_storage<sizeof(Foo),alignof(Foo)> foo;
new(&foo) Foo;
/* destructor never called even though a Foo
lives in block scope and its storage is
free'd
*/
}
C++ unions: union Foo {
Foo() { std::cout << "Foo()" << std::endl; }
~Foo() { std::cout << "~Foo()" << std::endl; }
};
{
Foo foo();
/* destructor never called */
}
Rust: struct Foo;
impl Drop for Foo {
fn drop(&mut self) {
println!("drop!");
}
}
{
let _ = std::mem::ManuallyDrop::<Foo>::new(Foo);
/* destructor never called */
}
etc.> There are some situations where objects with block scope do not have their destructor called e.g. `_exit()` called, segfault, power cable pulled out. But in that sense nothing is guaranteed.
This is pretty much why it is impossible for a programming language to guarantee that destructors will be called.
Might seem trivial, but even when you have automatic storage, any of the things you mention can happen, such that destructors won't be reached.
In general, C++, Rust, etc. cannot guarantee that destructors will be called, because it is also trivial to make that impossible once you start using the heap (e.g. a `shared_ptr` cycle will never be freed).
> forget is not marked as unsafe, because Rust's safety guarantees do not include a guarantee that destructors will always run.
This was a problem in Rust when scoped threads relied on destructors being run.
I'm not sure it's possible to force any code to be run (e.g. a process can be terminated at any time) although a closure might offer slightly stronger guarantees in some situations.