> In what sense do you disagree?
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).