lpapez
I kind of emphatize with the author raging at "just copy C++ bro" proposals because at $TWO_JOBS_AGO I had to deal with an "Architecture Team" full of Very Senior(tm) people who would show up uninvited and give advice like "did you know you can pee and poo at the same time?"

Of course, but if you bothered at all to understand the constraints, you would have seen it is not actually that simple in our case.

And my project was several orders of magnitude simpler than the C standard.

slaymaker1907
I'd argue it barely works in C++ as well. I've seen so many poorly implemented classes that violate the very complicated 3/5/0 rule. It's much easier to do RAII correctly in Rust since people aren't constantly working with raw pointers and since objects which are moved somewhere else are not dropped like they are in C++.

One variant that I think might work even better than RAII or defer in a lot of languages is having a thread local "context" which you attach all cleanup actions to. It even works in C, you just define cleanup as a list of

    typedef void(cleanup_function*)(void* context);

 which is saved as into a thread local. Unlike RAII, you don't need to create a custom type for every cleanup action and unlike the call-with pattern from functional programming, lifetimes of these lists can be non-hierarchical.
However, I'm still glad to see defer being considered for C. It's a lot better than using goto for cleanup.
gary_0
In other words, C structs and C++ structs are not the same thing (although C++ can usually handle C structs too). C structs are Plain Old Data. C++ structs are "objects" and there are pages and pages of rules in the C++ Standard about what that means, and there's no way the C Standard can incorporate all that. And you can't drag any C++ struct/class features into C without dragging in all those rules with them.
guillaumec
I notice more and more pushes to 'improve' C and turn it into something it should not become. I feel like the C++ community gave up on C++ because of the growing complexity and so turned to C with the hope of adding to it the good parts of C++ without the ugliness. But this is of course hopeless: every added feature will create new issues that will be solved with new features until the language becomes too complex for anyone to fully understand.
jokoon
I wish there was some way that you could configure a C++ compiler to just disable certain features of the language, or enforce good practices.

But that's already what linters/static analyzers are doing? But then, why not integrate those tools directly in a C++ compiler instead?

With cpp2/cppfront, Herb Sutter is already building some sort of a "sane" subset of the C++ language, maybe because you cannot achieve good practices without having a new syntax.

C++ seems to have the same problem of javascript: it has annoying "don't-do-that" use cases, although it seems insanely more complicated to teach good C++ practices.

pornel
> “just ban simple automatic storage duration structure copying” is a terrible usability and horrific ergonomics decision to make

This sounds like a great idea to me! Rust disables implicit copying for structs with destructors, and together with move-by-default, it works really well. Unlike PoD structs, you don't need to heap allocate them to ensure their uniqueness. Unlike copy constructors, you don't need to worry about implicit copies. Unlike C++ move, there's no moved-from junk value left behind.

einpoklum
A C++ code design note:

The initial example in the article is anti-idiomatic, because it imbues the larger class with a RAIIness which can be limited to just one element of it:

    struct ObjectType {
      int a;
      double b;
      void* c;

      ObjectType() : a(1), b(2.2), c(malloc(30)) { }
      ~ObjectType() { free(c); }
    };

It's only the c member that really requires any special attention. In this particular case. So, there should be something like a `class void_buffer` which is a RAII class, and then:

    struct ObjectType {
      int a;
      double b;
      void_buffer c;

      ObjectType() : a(1), b(2.2), c(30) { }
    };
and actually, let's just not sully the set of constructors, but rather have:

    struct ObjectType {
      int a;
      double b;
      void_buffer c;

      static ObjectType make() { 
        return ObjectType{ 1, 2.2, 30 }; 
      }

    };
and now instead of a complicated bespoke class we have the simplest of structs; the only complexity is in void_buffer.
Measter
Maybe I just suck at reading, but I'm not sure I get the argument for why function overloading and constructors are required for RAII. Is it some interaction with C and C++'s object models that I clearly didn't understand?
eschneider
It would seem that if you want C with RAII, you...use C++ and limit the features you use. QED.
nicebyte
I respect Jean-Heyd very much, but I'm unconvinced by this article. First, the whole name mangling discussion is completely irrelevant to the issue and can be omitted. Second, one could tack on both copy and move constructors on to C in order to solve the double-free issue, in much the same way regular ctors are tacked on in the email proposal. In fact, I would argue that it is _necessary_ because A in RAII stands for Acquisition not Allocation. "Acquisition" implies ownership, which can be transferred or shared, so your copies and moves _have_ to have a special meaning to them. The fact that the proposal is bad or incomplete does not mean that it is "impossible" to have RAII in C. I don't claim that it _is_, but reading this did not reveal to me anything fundamental that would preclude RAII, only that all the preceding RAII proposals have been sloppy.
iainmerrick
This is obviously a bit of a rant, and intended as such, but it’s really well thought through and well-argued too.

I haven’t seen this distinction laid out so clearly before:

Every other language worth being so much as spit on either employs deep garbage collection (Go, D, Java, Lua, C#, etc.) or automatic reference counting (Objective-C, Objective-C++, Swift, etc.), uses RAII (Rust with Drop, C++, etc.), or does absolutely nothing while saying to Go Fuck Yourself™ and kicking the developer in the shins for good measure (C, etc.).

GC, ARC, RAII or GTFO, those are the options. That’s right!

I always come away from these discussions with more respect for Objective-C -- such a powerful yet simple language. I suppose Swift is the successor but it feels very different.

Although, Obj-C only really came into its own once it finally gained automatic reference counting, after briefly flirting with GC. At that point it was already being displaced by younger and more fashionable languages.

jay-barronville
C is the ultimate WYSIWYG language (provided you understand the semantics of your target architecture and assuming a non-buggy compiler). The language is relatively simple. The standard is accessible. I’d like it to remain that way. I don’t need C to adopt any other “modern” language features.

C11 provided a few worthwhile improvements (i.e., a proper memory model, alignment specification, standardized anonymous structures/unions), but so many of the other additions, suggestions, and proposals I’ve seen will just ruin the minimal nature of C. In C++, a simple statement like `a = b++;` can mean multiple constructors being called, hidden allocations, unexpected exceptions, unclear object hierarchies, an overloaded `++`, an overloaded `=`, etc. Every time I wish I had some C++ feature in C, I just think about the cognitive overhead it’d bring with it, slap myself a couple times, and go back to loving simple ole C.

Please don’t ruin C.

throwawaymaths
How about instead of RAII built into the compiler, you define destructor functions for each datatypes that you care to and have a sidecar or compiler plugin or hell even a linter check that those destructors have been called when a variable of that type goes out of scope?

If you miss a destructor event, without configuring the addon "yes I really meant that", the addon halts the compilatoin at best, or returns nonzero for ci at worst.

potbelly83
I'm confused why are they trying to implement name mangling in C? Are they trying to use the C++ compiler to implement the RAII assembly code and then link that back into C? Wouldn't a smarter approach be to do a C version of what C++ does?
Xeamek
Is RAII even wanted? I mean, in the name, 'Resource acquisition is initialization' it talks about the initialization part. But while not super versed in cpp, it looks like what everybody wants is actually the de-initialization part, which doesn't seem to be inherent to RAII, no?

It's a bit confusing to have a 'thing' mention one mechanism in its name, but actually being valuable by ensuring some other mechanism

rqtwteye
I always find it interesting to see calls to mallow and free in C++ code. I don't recall using malloc/free in many years in C++. It's always new/delete.
ezoe
I really don't understand why the author is so mad at these armchair professionals who think they know better.

You are proposing to change the C language. The risk is great even the smallest change will break the existing code. If you can't convince all of the stakeholders, it's better not to change it. Keep the status-quo.

wrs
>The utterly pervasive and constant feeling that a lot of people – way too many people – are really trying to invent these things from first principles and pretend like they were the first people to ever conceive of these ideas… it feels pretty miserable, all things considered. Going through life evaluating effectively no prior art in other languages, domains, C codebases as they exist today, just… anything.

Oh man, I hear ya. And in a lot more domains than computer language design. Is it inexperience? Impatience? The tendency for search results to be filled with low-quality and high-recency content? The prioritization of hot-take blog posts and Reddit comments over books?

astral303
Sad that C is still being utilized with a serious face. If you can't be bothered to develop in C++ and only pay for what you use, RAII is like your last problem.
tester756
>There is no wibbly-wobbly semantics like .NET IL finalizers

there is dedicated mechanism to achieve RAII-likeness in .NET: try-finally construct

kalekold
Use D's -betterC flag?

https://dlang.org/spec/betterc.html

PaulDavisThe1st
If you're reading these comments (and maybe contributing to them) about various arcane details of C++ and the differences with C, there's one thing you're not doing ...

... actually writing code that gets the job done ... in C++.

julian_t
Is there a law, like Betteridge's Law, that says "the answer to any question that says 'why not just' is 'it isn't as simple as that'"?
wakawaka28
Because you can just use actual C++ lol...
lionkor
C has scopes. Add destructors. That's pretty much all you need to get most of the benefits of RAII.

You can add `defer` instead, but regardless, this has nothing to do with C++. You can implement safety features without having to copy the arguably worst language in the world, C++. I like C++, I wrote many larger projects in it, but it sucks to the very core. Just add RAII to C.

yason
RAII is just automation and semantic sugar for something like this (or the equivalent set of goto labels that do the freeing at the end of the function):

    {
      void *buffer = malloc(SIZE_MAX);
      if (buffer) {
        if (!do_stuff(buffer)) {
          free(buffer);
          return;
        }
        more_stuff(buffer);
        free(buffer);
      }
      return;
    }
If you wanted something like that in C it doesn't need to emulate C++ style RAII with classes and strongly typed constructors. It could look like something like, for example, where you just define pairs of allocator and free functions:

    allocdef void *autobuffer(malloc, free);
    ...
    {
      autobuffer buffer(SIZE_MAX);

      if (buffer) {
        if (do_stuff(buffer)) {
          return;
        }
        more_stuff(buffer);
      }
      return;
    }
The implementation would effectively be a Lisp style macro expansion encoded in the C compiler (or preprocessor) that would just basically write out the equivalent of the first listing above.