struct LevelDB {
handle: *mut leveldb_database_t
}
impl Drop for LevelDB {
fn drop(&mut self) {
unsafe { leveldb_close(self.handle) };
}
}
What happens in detail when values drop?
Rust generally guarantees drop order (RFC1857)
Values are dropped at the end of their scope
The order is the reverse introduction order
Unbound values drop immediately
Structure fields are dropped first to last
Sometimes, certain actions must be taken before deallocation.
For this, the Drop
trait can be implemented.
struct LevelDB {
handle: *mut leveldb_database_t
}
impl Drop for LevelDB {
fn drop(&mut self) {
unsafe { leveldb_close(self.handle) };
}
}
Destructors cannot return errors.
Explicit destruction of a value through a consuming function. This cannot be statically enforced currently.
Implementing a Drop
-bomb (a failing destructor) can make sure this error is caught early.
Rust also has another error mechanism: panic!
fn main() {
panicking_function();
}
fn panicking_function() {
panic!("gosh, don't call me!");
}
In case of a panic, the following happens:
The current thread immediately halts
The stack is unwound
All affected values are dropped and their destructors run
Panics are implementation-wise similar to C++-Exceptions, but should only be used for fatal errors. They cannot be (normally) caught.
The affected thread dies.
Panicking across FFI-boundaries is undefined behaviour. In these cases, panics must be caught. For cases like this, there are std::panic::catch-unwind and std::panic::resume-unwind.
std::panic::set_hook allows setting a global handler that is run before the unwinding happens.
In general, Result
is always the right way to propagate errors if they are to be handled.
In some environments, unwinding on panic!
is not very meaningful. For those cases, rustc
and cargo
have a switch that immediately aborts the program on panic.
The panic hook is executed.
Panicking while a panic is being handled - for example in a destructor - invokes undefined behaviour. For that reason, the program will immediately abort.