It’s pedantic, but in the malloc example, I’d put the defer immediately after the assignment. This makes it very obvious that the defer/free goes along with the allocation. It would run regardless of if malloc succeeded or failed, but calling free on a NULL pointer is safe (defined to no-op in the C-spec).
Defer available in gcc and clang
131–140 of 262 posts
Re: Defer available in gcc and clang
#132Would defer be considered hidden control flow? I guess it’s not so hidden since it’s within the same function unlike destructors, exceptions, longjmp.
It's one of the most commonly adopted feature among C successor languages (D, Zig, Odin, C3, Hare, Jai); given how opinionated some of them are on these topics, I think it's safe to say it's generally well regarded in PL communities.
Re: Defer available in gcc and clang
#133Re: Defer available in gcc and clang
#134I took some shit in the comments yesterday for suggesting "you can do it with a few lines of standard C++" to another similar thread, but yet again here we are. Defer takes 10 lines to implement in C++. [1] You don't have to wait 50 years for a committee to introduce basic convenience features, and you don't have to use non-portable extensions until they do (and in this case the __attribute__((cleanup)) has no equiva…
Why is this a relevant comment? We're talking about C, not C++. If you wanted to suggest using an alternative language, you're probably better off recommending Zig: defer takes 0 lines to implement there, and it's closer to C than what C++ is.
My comment is targeted towards the programmer who is excited about features like this - you can add an extra two characters to your filename and trivially implement those improvements (and more) yourself, without any alterations to your codebase or day to day programming style.
Re: Defer available in gcc and clang
#135Earlier quoted context omitted.
One small nitpick: you don't need check before `free` call, using `free(NULL)` is fine.
But it does keep one in the habit of using NULL checks.
In other words, the first time you access a "freshly allocated" non-null pointer you may get a page fault due to insufficient physical memory.
Re: Defer available in gcc and clang
#136Would defer be considered hidden control flow? I guess it’s not so hidden since it’s within the same function unlike destructors, exceptions, longjmp.
Of course, that idea already isn’t correct in many languages; function arguments are evaluated before a function is called, operator precedence often breaks it, etc, but this moves entire statements, potentially by many lines.
Re: Defer available in gcc and clang
#137As others have commented already: if you want to use C++, use C++. I suspect the majority of C programmers neither care nor want stuff like this; I still stay with C89 because I know it will be portable anywhere, and complexities like this are completely at odds with the reason to use C in the first place.
Then why not even better, K&R C with external assembler, that is top. /s
Is that supposed to exacerbate how poor that choice is. External assembly is great.
Re: Defer available in gcc and clang
#138Earlier quoted context omitted.
This example is exactly why RAII is the solution to this problem and not defer.
defer is literally just an explicit RAII in this example. That is, it's just unnecessary boiler plate to wrap the newResource handle into a struct in this context. In addition, RAII has it's own complexities that need to be dealt with now, i.e. move semantics, which obviously C does not have nor will it likely ever.
In the example above, the question of "do I put defer before or after the `if err != nil` check" is deferred to the programmer. RAII forces you to handle the complexity, defer lets you shoot yourself in the foot.
Re: Defer available in gcc and clang
#139Earlier quoted context omitted.
But it does keep one in the habit of using NULL checks.
It is pointless, because in Linux all you get is a virtual address. Physical backing is only allocated on first use. In other words, the first time you access a "freshly allocated" non-null pointer you may get a page fault due to insufficient physical memory.
Re: Defer available in gcc and clang
#140In C I just used goto - you put a cleanup section at the bottom of your code and your error handling just jumps to it. #define RETURN(x) result=x;goto CLEANUP void myfunc() { int result=0; if (commserror()) { RETURN(0); } ..... /* On success */ RETURN(1); CLEANUP: if (myStruct) { free(myStruct); } ... return result } The advantage being that you never have to remember which things are to be freed at which particular…
One small nitpick: you don't need check before `free` call, using `free(NULL)` is fine.
There are several other issues I haven't shown like what happens if you need to free something only when the return code is "FALSE" indicating that something failed.
This is not as nice as defer but up till now it was a comparatively nice way to deal with those functions which were really large and complicated and had many exit points.