I don't want to jump on the "Rust fixes everything" train, but lifetimes, scope-based destructors and reference counted pointers seem like they help with this sort of thing beyond just preventing literal accesses of freed memory; they can make sure objects are around when you need them and that they're destroyed automatically when you don't anymore.
Of course, you don't get it all for free; you have to wrestle with mutability and lifetimes, which can get hairy.
Of course, you don't get it all for free; you have to wrestle with mutability and lifetimes, which can get hairy.