Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I would be interested how you "fix-up object lifetimes"?


Sure, it is pretty simple, just esoteric.

The compiler attempts to track object lifetimes for the purpose of optimization e.g. if the object contains a notionally immutable value it doesn’t have to re-read the value during the object’s lifetime. A lot of compile-time code optimization is based on knowing when an object at a memory address is changed or destroyed. If the objects don’t get destroyed but merely disappear, or worse, are replaced with a different object at the same address, and the compiler can’t see that at compile-time then the compiler assumes it doesn’t happen. This violates strict aliasing rules in C/C++ even though there are legitimate reasons for this to occur. C/C++ systems code, like Linux, commonly disable strict aliasing rules because it causes undefined behavior, even though it also disables certain optimizations.

In the last several revisions of C++, they have added blessed methods of informing the compiler when these object lifetime rug-pull situations occur, so that it can optimize around them without disabling the optimizations enabled by strict aliasing. This includes functions like std::launder, which acts like a constant folding barrier i.e. the compiler can’t assume that constants at that address prior to the barrier call are still operative when generating code. There are a couple other functions in C++23 that explicit take a memory address and explicitly start a new lifetime with an arbitrary type, without constructing a type at that address; these are no-ops, all of these functions are compiler annotations, they don’t generate code. These are blessed ways of doing more hack-ish ways of effecting the same result in recent versions of C++ (e.g. the memmove/launder trick). In old versions of C and C++, the ways of doing this were technically undefined behavior but the compiler writers unofficially provided ways to work around this that would behave as needed since it had valid use cases, which is not a great way to work.

This doesn’t just affect lifetimes, though that is most of what the fix-up is about. Mutability of references is similarly fuzzy and it is impossible for a good design to guarantee that multiple mutable references don’t exist, so you need other mechanisms to guarantee they never conflict. However, these fix-ups are above the level of the compiler.

In the extreme case of database kernels, most objects have an ambiguous lifetime and uncertain address. Consequently, you have to create object reference wrappers that hide what is required to ensure strictly defined behavior in these cases and to ensure conflicts can’t happen. Wrapping your object references with some small hygienic functions can eliminate the issue.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: