3 ms·
> then anything that reduces readability in the sense of "I can see everything that is going on" is very bad. Nonsense. So called "kernel C" still uses functio
by kllrnohj 4y ago
> then anything that reduces readability in the sense of "I can see everything that is going on" is very bad.
Nonsense. So called "kernel C" still uses functions, and lots of them, scattered over thousands of files. You never "see everything that is going on." And "kernel C" also uses function pointers and macros, further preventing you from "seeing everything that is going on."
Having written and read lots and lots of C++, RAII being "hidden" is hugely overblown by the diehard C crowd. It's really not hidden at all, first of all (it's often right there in the type - pretty hard to forget that unique_ptr is going to call delete, for example). And second it goes so so far in preventing resource leak bugs, which is also something kernels and low level code care a lot about. In fact, they almost always care far more about runtime correctness on this than readibility. The benefits RAII provide here so massively outweigh the "hidden" concerns it's almost laughable.
> You don't want to find out that some stray destructor did something that should not have happened in e.g. an interrupt context, or while the current thread's memory management is in an intermediate state. That is not correct by default, it is "wrong and you didn't even tell me".
RAII isn't just randomly injected. It's governed by the types you use. If a given type cannot be safely cleaned up in a given context, then it probably also wasn't safe to get in that context in the first place. Which the type should be communicating. So no it's not "wrong by default" since the initial (explicit!) acquisition was the "wrong" part, not the cleanup.
Regardless, it's not like C helps here at all. You still have to call the cleanup function for your given data, and that cleanup function may change without your interrupt handler knowing about that change.
- anyfoo 4y ago> Having written and read lots and lots of C++, RAII being "hidden" is hugely overblown by the diehard C crowd. I work on low level projects which use both at the same time. > If a given type cannot be safely cleaned up in a given context, then it probably also wasn't safe to get in that context in the first place. Not true. As a quick example, the destructor might try to take some statistics, which might not be safe in an interrupt context, or when a thread is (internally) in an intermediate state. There might also be multiple ways to get rid of the type. This was an "obvious" example, the ones that bite you are the non-obvious ones of course. And yes, I have anticipated both the "but you still call functions in C" and the "functions may change" comment. True, but you call those functions explicitly, at a very explicit point (which you can also surround with other code), and anyone who works on a cleanup/destructor-like function can very easily figure out all call sites. My point is precisely that you tend to run into these icky issues when deep in the bowels of a system, not when writing a smartphone app. > And second it goes so so far in preventing resource leak bugs, which is also something kernels and low level code care a lot about. Kernels do care about that, true. But if you exchange resource leak bugs for invalid state, which translates much more happily into security bugs, you are definitely worse off.
- kllrnohj 4y ago> Not true. As a quick example, the destructor might try to take some statistics, which might not be safe in an interrupt context, or when a thread is (internally) in an intermediate state. Which is a problem you also have in C. If someone is going and adding, say, lock duration statistics they aren't auditing all the C call sites just like they wouldn't be doing that with C++ destructors. Which you can search for, fwiw. You seem to be under an incorrect assumption that you can't find those usages. You can. > There might also be multiple ways to get rid of the type. This is not incompatible with RIAA. See for example unique_ptr's optional destructor. Of course, you're always free to just not use RIAA in those specific contexts.
- anyfoo 4y ago> Which is a problem you also have in C. Personal opinion will differ, but after reading and working on both C and RAII-heavy C++ low level code for many years (though I don't do the C++ one anymore), the low level C code just feels like fresh air when auditing.[1] It's all so explicit. For high level, as mentioned initially, I feel the opposite, as the boilerplate gets in the way. > Of course, you're always free to just not use RIAA in those specific contexts. That's my point, is it not? RAII in high level code, not in low level code. I did not claim they have to be in different code bases. And I am really not afraid of abstraction, my favorite language is Haskell. But that's so high level, and so far from the metal, that every function looks pure, and every value is lazy by default. [1] Personally, I think Rust would be my choice.