I've been a professional C++ programmer for almost two decades (and a C++ amateur for almost a decade before that). I've written large amounts of fairly advanced C++ using the latest standards.
My current job however, is all plain C.
One of the interesting (and, for a C++ fan like me, disturbing) things I've found is that the cognitive load is much lower when writing plain well-structured C.
Sure, you need to remember to release that lock and free that memory but this you can do in a very structured way. What you win over C++ is that you don't need to view each line of code with suspicion ("What happens if this line throws an exception?", "I wonder what this line will cost in terms of performance?", "Could this operation cause a cascading destruction of objects I'm going to access further down?").
I love RAII, yet I've debugged enough crashes where "seemingly innocuous operation destructs some local object that has an owning reference to an object that shouldn't be destructed just yet and BAM!", that I'm beginning to doubt its usefulness outside of an exception-generating language (in C++ it's essential for proper exception-handling).
The critical question is: what does the error rate look like for code of similar complexity? It's very possible that C programmers will try to keep things simple, because the language doesn't support them and they have to be extra careful. The flip-side is that they probably can't develop projects as complex as C++ would enable them to.
It's always bothered me how complex of an operation people seem to think this is.
errno = pthread_mutex_lock(&m);
if (errno == 0) {
do_something();
pthread_mutex_unlock(&m);
}
Short of a segfault or 'do_something' doing something really, unusually stupid, you can't avoid freeing the mutex.Only difference? We were in Python.
This is not even remotely the worst thing about mutexes though, so it wouldn't be why I would suggest avoiding them.
There's also the goto pattern, but anytime you separate a lock from an unlock by more than a screen's worth of text, they're forgotten.
Seems like that padded floor has some rusted nails hiding right behind the pretty fabric.
RAII is not something limited to Rust, or C++, or any other language. The abstraction underpinning RAII can be done and has been done in C; you can see it done repeatedly in the code for collectd.
Its up to the developers to make their programs safe and reliable. No language to date will do that for them.
But languages do make a huge contribution. For example, Rust, Ada and Modula-3 are all much safer by defaults alone compared to C. Most Rust code sits outside unsafe blocks, so the existence of this feature does not prove there is no point to Rust.
I didn't say anything along those lines. I said that it's up to developers to make their programs safe.
Defaults matter, no doubt. But they are not a silver bullet; greater base safety can even cause people to become lax when thinking about safety, resulting in even bigger problems. Why do Python developers accept and parse untrusted pickle objects? Because Python is safe, and they don't have to think about what's going on under the hood.
It's indirectly related to computer programming, but a study was done in Europe which showed that crashes in AWD vechicles were, on average, much more severe than 2WD vehicles. Why? Because of the added stability of AWD, people drove faster in adverse conditions.
This is a false equivalency.. It's akin to saying "you can hit your thumb putting in a nail with any tool, so you might as well use a rock not a hammer since they're both bad".
Yes, you can make mistakes in any language, but that's not a reason to ignore modern tooling and advances and continue.
Other languages allow us to build abstractions and solve mistakes in ways which are just impossible with C... and without those abstractions, it's just needlessly difficult to keep all the state in your head and write correct code.
An easy example of this is locking and ownership. In C, mutexes are managed manually and what they hold is by convention. It's easy to write races or accidentally deadlock (again as evidenced by such a bug in the kernel existing every few weeks).
In languages with RAII, python's "with", etc, you can't forget to unlock the lock. It's one less thing to think about.
In languages like rust, it's possible to model in the type system that a given resource can only be accessed while a mutex is locked. Again, one less way to make a mistake.
C has no ability to provide or build abstractions that are this robust.
Using C is, more often than not, like using a rock to hammer in a nail.
> Just because some people prefer to live in padded rooms
With C, people are living in a room where the floor is lava and nails coat most surfaces.
I'll take my room that's carpeted, and if I need to pull a stunt and rip up the carpet, sure, I can do that, but at least I can walk normally most of the time.