5 ms·
This reads like cope because you're re-inventing RAII from first principles. I cannot take this seriously as tutorials on robust Zig Allocation Pools will stor
by hugmynutus 3mo ago
This reads like cope because you're re-inventing RAII from first principles.
I cannot take this seriously as tutorials on robust Zig Allocation Pools will store a deinit method for each item within the pool, so when the pool deinits, all internal objects can be deinit'd.
That is just RAII & dtors from first principles, except with extra overhead of manually storing fat pointers yourself (and the bugs that come with this). Instead of using a language with builtin guarantees & optimizations around handling this so your object pools don't need to carry around a bunch of function pointers. C++ has aggressive de-virtualization passes so at runtime a lot of the 'complex object hierarchies' can be flattened to purely static function calls.
- jstimpfle 3mo agoI've argued elsewhere some things that are wrong with RAII and C++ objects in general. Here I would just like to mention that if you have to rely on "de-virtualization" passes, you're in a miserable situation architecturally. If you have code where the overhead of virtual function calls might be too much to pay, don't do virtual functions then. End of story. To deconstruct a pool of objects, I don't see what should ever be wrong with a function pointer. The overhead of loading the function pointer will get divided by the number of objects being deconstructed. Care to explain what's the issue here?
- hugmynutus 3mo ago> I don't see what should ever be wrong with a function pointer. [...]Care to explain what's the issue here? 1. You're writing code you don't have to 2. That adds runtime overhead 3. That when you screw up has non-trivial security & resource management side effects This is objectively indefeasible in nearly any vaguely professional context.
- jstimpfle 3mo ago1. No, you're not writing code you don't have to. It's not different to implementing this as non-virtual methods, in fact I'd argue doing simple functions is more straightforward. 2. And the code being compiled is abstract & generic, it won't be instantiated for every type and bloat the executable or instruction cache. 3. Security concerns: With C++ virtual methods every object carries a mutable pointer too (to a vtable containing function pointers). What resource management side effects please?
- kllrnohj 3mo agoRe #3: vtable pointers aren't mutable...?
- jstimpfle 3mo agoOf course they are. The pointers to the vtable are part of the object. They aren't mutable fields as per the language, but for security concerns it doesn't matter what the language thinks. Being part of the object, the vtable pointer has to live in a writeable memory mapping (like stack / heap).
- Conscat 2mo agoClang pointer authentication makes any type of vtable attack impossible in C++.
- jstimpfle 2mo agoFair enough, this is an extension though and I suppose you could use it with manually constructed vtables as well?
- kllrnohj 2mo agoThen I don't understand your argument. If you're just saying what could go wrong with heap corruption, then your vtable complaint also applies to storing function pointers in arena allocators in Zig? Zig doesn't have anything special here?
- jstimpfle 2mo agoI asked you what's wrong with pool destructor function pointers. You gave a reason what's wrong and I refuted it. So no, I'm not saying that storing a function pointer is special, just that nothing's wrong with it. (And implying that since there's nothing wrong and it's probably the most straightforward thing to do, it's also probably the right thing).
- CyberDildonics 2mo agoI've argued elsewhere some things that are wrong with RAII and C++ objects in general. You claimed there were problems many times for sure, I don't think you came up with any evidence of those problems.
- jstimpfle 2mo agoYou keep "asking" for evidence but the only evidence presented by yourself is that you have merely surface-level understanding of the subject matter, and are looking for arguments, not insight and critical examination.
- CyberDildonics 2mo agoIt's your claim that destructors are harmful so the burden of proof is on you. People use them because by default values have scope based lifetimes and destructors unify the handling of stack based values which require no explicit cleanup with data structures that heap allocate, which require no explicit cleanup once the destructor is implemented. This is the opposite of C where even though the resource cleanup needs to happen on scope end, it is not automatic, and so becomes a source of bugs. This is exaggerated when there are multiple returns, gotos, macros and other sources of branching especially for error handling. This automation also removes boilerplate so there is less management that needs to be done when using data structures. What was your evidence or explanation?
- jstimpfle 2mo ago> It's your claim that destructors are harmful so the burden of proof is on you. I have given a variety of arguments why I think the C++ RAII specifically has downsides. You can accept them or ignore them, but don't act like I didn't give arguments. > People use them because by default values have scope based lifetimes and destructors unify the handling of stack based values which require no explicit cleanup with data structures that heap allocate, Once again you're explaining beginner C++ do me. Are you still doubting if I understand this argument? My response to this was and is, if you have primarily stack scoped lifetimes, you are writing beginner programs. This is scripting and plumbing. It's not interesting to me. Systems programming is not so much about stack scoped lifetimes. RAII systematicing object lifetimes and cleanup, thus enabling exceptions and implicit or uncontrolled control flow, may sound nice on paper, but turns out we shouldn't want them in the first place. What RAII leaves for me is a system that will automatically call nested object's destructors when I delete something. It's not something I want in general, I think it has more downsides than upsides for the code I'm writing. I've actually tried to use RAII many times and I've concluded it doesn't work for me. > This is exaggerated when there are multiple returns, gotos, macros and other sources of branching especially for error handling. If I were you, my response would be: The burden of proof is on you, show the evidence. But my answer is, yes that is right, but everything is a tradeoff, and the issues caused by manual cleanup are also somewhat exaggerated by C++ people, and the issues caused by blindly buying into the corset of C++ types are not well understood by C++ zealots (I've done my best at explaining them). Issues caused by C approach are also a matter of design and approach to programming in general. It also depends on the actual problem you're solving. The linux kernel for example doesn't exactly have the easiest or most beautiful code to follow, but surely it's one of the most technical codebases out there, one that solves difficult problems (performant resource multiplexing for programs that it doesn't even know). On the other hand, the debugger code base I've referenced doesn't have any gotos for example, nor even early returns (or almost none, not sure). Find me a single example of programs that run as fast and are as productively maintained as these two codebases in their respective areas? I believe there aren't any. This should be plenty evidence to a reasonable mind, but that isn't you.
- MintPaw 3mo agoThis is a general problem with destructors, you can't "batch delete" objects. To free a lot of stuff you're required to go pointer by pointer through the tree to clean up each object. To get real performance gains from pools you can't have per-object/subobject custom cleanup code.
- aabhay 3mo agoNot necessarily. Drop semantics are just syntactic sugar, and can thus be aggressively inlined or auto vectorized by the compiler.