Why are lifetimes in FFI/unsafe hard to understand?


#1

Over on Reddit I made a post asking for feedback on the rewrite of my FFI guide. One user made a comment that it’s hard to reason about lifetimes/object destruction in FFI code:

Ome thing that I al struggling at the moment is how to don’t free objects that will need to be managed by the C part in your rust code.

If you are writing a callback you will most likely get a pointer from C that you use for doing whatever, then, before to exit you may want or not to free such pointer.

If you don’t want to free the pointer it get hairy quite quickly.

This is a comment I’ve heard several times, but I’m not sure which bits people are struggling to understand and how to teach the concepts properly.

I’ve personally found that applying Rust’s concepts of ownership and lifetimes to my C/C++ code works really well (i.e. pretend to be the borrow checker or imagine where rustc would normally insert calls to drop()), but other people will probably have their own way of understanding things. A hefty dose of the KISS principle also helps when I start trying to be too smart for my own good :stuck_out_tongue:

Can you think of an example where ownership and lifetimes have gotten confusing when using unsafe or dealing with FFI?


#2

I’m not sure what the poster meant by

Not freeing the pointer would be the default action. You may want to ask them for clarification (if you haven’t yet - I didn’t peek at the thread).


#3

I think they were doing something funny with the callback and didn’t quite understand the system’s ownership semantics. Usually I think of a callback as a method which takes a reference to our state object, but it sounds like the OP was trying to free the object in a callback which may be fired multiple times.

The usual way of doing things is either to give the library some sort of finalizer function which calls our destructor (kinda like what I did in the dynamic loading chapter), or you’ll create the item in a higher stack frame, pass in a reference to the C code that’s firing our callback, then once that code is done you destroy everything.