3 ms·
I'm glad MTE is catching on, I think it's the future for C and C++'s memory safety story. Hopefully intel comes out with something for it soon too! Vale is tak
by verdagon 4y ago
I'm glad MTE is catching on, I think it's the future for C and C++'s memory safety story. Hopefully intel comes out with something for it soon too!
Vale is taking a similar approach at the language level, by putting a generation at the top of every allocation [0] and it's proving pretty fast. It's also proving more accurate, since its generations are larger; MTE uses 4-8 bits, and generational references use 32-64.
It would be cool to see C++ itself embrace generational references in the standard library (perhaps via a std::gen_ptr?), it would give us some memory safety without needing to use the heap, which would be a big improvement over modern C++'s encouragement of std::shared_ptr.
[0] https://verdagon.dev/blog/generational-references https://verdagon.dev/blog/generational-references
- dataflow 4y agoConfused, why are generational references being compared with reference counting? One is intended for shared ownership, the other is intended for memory safety. They seem completely orthogonal/unrelated to each other; they look like complements rather than competitors. I'd also be interested in knowing whether they compared against a single-threaded reference counter or a multi-threaded reference counter. The atomics in a thread-safe RC severely impact performance; I hope they didn't compare that against GR.
- verdagon 4y agoI see RC and GR as two methods of ensuring memory safety: one that extends the life of an object, and one that asserts the object is still alive. They both protect us from vulnerabilities and UB, but with different approaches. Yep, it was compared to single-threaded RC for fairness.
- dataflow 4y agoRC isn't there to protect you from vulnerabilities though. It's there to let you share ownership. There's some side benefits in that regard, but the latter can't substitute for the former except in cases where the former is unnecessary to begin with. As an analogy, imagine comparing a safety knife, a kitchen knife, and (a safe version of?) an axe with each other, and touting how much lighter/safer/whatever the first one is compared to the others. Of course that's correct, and you can make the comparison, but there isn't (or at least shouldn't be?) a huge market of people out there using an axe in the kitchen who could've just used a knife instead, so it's a weird choice of a market to sell an otherwise-great product to. (And thanks for clarifying the single-threaded aspect.)
- MaulingMonkey 4y ago> It's there to let you share ownership. And ownership - shared or otherwise - is a great way to eliminate the use-after-free bugs that would otherwise be caused by naively attempting to create a non-owning, borrowing reference to something else. It is in fact the primary use of refcounted pointers in many C++ codebases I've worked with - perhaps with a single std::shared_ptr and several std::weak_ptr s, meaning you're not really sharing ownership per se despite the refcounted nature - or perhaps with multiple std::shared_ptr s out of sheer laziness. I've had my share of C++ code reviews dinged for perfectly valid code containing non-owning references, simply because such code could be fragile and prone to use-after-free heisenbugs in the face of refactoring, and my reviewers were right to do so. Things are safer in Rust - you can play fast and loose with storing &str s and rely on the borrow checker to catch your mistakes - but playing fast and loose with storing std::string_view s will lead to slipped release dates as you chase 11th hour heisenbugs. Store a std::string or std::shared_ptr<std::string> instead, even if it's "unnecessary". > there isn't (or at least shouldn't be?) a huge market of people out there using an axe in the kitchen who could've just used a knife instead Some of us are out camping in the wilderness that is C++ gamedev, and want to make kindling. Do I need to pack a whole axe, or would a knife I need for other reasons anyways make do and lighten my backpack? And even if that's a small market, it's still entirely a reasonable market, and for advertizing to that audience - however niche - comparing said tools would be an entirely justifyable approach to selling the product. I also think you underestimate the size of said market.
- masklinn 4y ago> It is in fact the primary use of refcounted pointers in many C++ codebases I've worked with - perhaps with a single std::shared_ptr and several std::weak_ptr s [...] Store a std::string or std::shared_ptr<std::string> instead, even if it's "unnecessary". Uh, I've been wondering at the use case for rc::Weak, that seems like an interesting halfway point if you think borrowing should work but you can't get the compiler to accept it.
- mgaunard 4y agoshared_ptr is just a code smell. There aren't really many good use cases for shared ownership, using it is just a cop-out because you can't design code properly.
- pjmlp 4y agoMe too, pity that is something that only Solaris SPARC has had in production at scale for the last decade. C++ might be getting hazardous pointers thought, although most likely they will only make it to C++26.
- cyber_kinetist 4y agoYou can certainly implement generational pointers in C++ code without further language-level support (given that you’re using your own handmade object pools). Don’t know if this can get to the STL though, since it requires a malloc (or object pool) implementation tailor-made for it. I’ve implemented this in my current C++ game engine, and works wondrously well. You can even pack that generational index in the unused 16-bits of a 64-bit pointer, if you have further constraints (like a C library only allowing void* as userdata)!