Live data from Hacker News

Defer: Resource cleanup in C with GCCs magic

oshub.org

41–50 of 99 posts

Re: Defer: Resource cleanup in C with GCCs magic

#41
post #37

Earlier quoted context omitted.

Since the compiler will merge/fold what it appears to be a different logic sections of your code into a single one, you can never be sure what the release build codegen looks like unless you read the assembly.

If you check for null pointer before you dereference, then no the compiler cannot elide the check. If you check after dereferencing it, yes it can. But in this case why would you not check before dereferencing? It's the only UB-free choice.

Yes, it can. Why would you be checking the pointer for nullptr after you have dereferenced it? It makes no sense at all, so, compiler indeed can elide the nullptr check before dereferencing the ptr exactly because it is free to _always_ assume that the program is free of UB.

To be more precise GCC says "eliminate useless checks for null pointers" and what I am saying that you can never be sure what in your code ended up being "useless check" vs "useful check" according to the GCC dataflow analysis.

Linux kernel is a famous example for disabling this code transformation because it is considered harmful. And there's nothing harmful with the nullptr check from your example.

Re: Defer: Resource cleanup in C with GCCs magic

#42
post #30
post #14

Earlier quoted context omitted.

poor? If I use RAII I'd need to have a struct/class and a destructor. If I use defer I'd just need the keyword defer and the free() code. It's a lot more lean, efficient, understandable to write out. And with regards to code-execution timing, defer frees me from such a burden compared to if-free.

> If I use defer I'd just need the keyword defer and the free() code. Yeah, and not accidentally forgetting to call it. That's the big part. And before "True Scotsman will always free/close/defer!" - No, no they won't. Unless the compiler screams at them, or its enforced via syntax constructs, it will always slip through the cracks.

Well I'd have to pay all the friction of writing up a new type, and in some cases the type gets cubersome. Doubly so if your codebase requires extra some friction like 1 header for each type.

Also get over it. We got post-processor things like static analyzers, etc, and whatever AI code reminders/fixers that are coming up next. I'd prefer those over muddying up the code base.

Re: Defer: Resource cleanup in C with GCCs magic

#43
post #9
post #6

Earlier quoted context omitted.

`free(NULL);` will crash on some platforms that gcc supports, I believe.

It shouldn't https://pubs.opengroup.org/onlinepubs/7908799/xsh/free.html >If ptr is a null pointer, no action occurs.

While I agree it shouldn't, that particular document is the UNIX specification, not the C specification, so it does not apply to C compilers on non-UNIX platforms.

Re: Defer: Resource cleanup in C with GCCs magic

#44
post #19

Earlier quoted context omitted.

Not on all platforms! If you’re writing portable code targeting a lot of embedded platforms then you don’t want to rely on this optimization.

It's a platform-agnostic optimization in case of GCC so if your embedded Linux toolchain is based on GCC, and most of them are, it's pretty much the case that it will have this optimization turned on by default. > This option is enabled by default on most targets. On AVR and MSP430, this option is completely disabled.

Yes and if you’re targeting AVR, an extremely popular 8 bit micro, then it’ll be turned off.

Re: Defer: Resource cleanup in C with GCCs magic

#46

I don't understand why people insist on simulating a poor substitute for RAII with a feature that is itself almost decent RAII. > If malloc fails and returns NULL, the cleanup function will still be called, and there’s no simple way to add a guard inside free_ptr. free(NULL) is a no-op, this is a non-issue. I don't know what's so hard about a single if statement anyway even if this were an issue.

Not having RAII is precisely the reason I prefer C over C++ or Rust. I WANT to be able to separate allocation from initialization. I'm currently working with Arduino code and the API is a mess. Everything has a second set of manual constructor/destructor, which bypasses type-safety entirely. All only to shoehorn having existing, but uninitialized objects into C++.

Both C++ and Rust allow that? Having niche behaviour not be the default makes sense, but both know it's needed and therefore allow it?

(C++ lets you malloc and then placement new (just casting the pointer like C does is UB, but it's being fixed for trivial types) and Rust has both plain alloc and Box>)

There are a lot of other reasons not to use them, but yours is a made up strawman.

Re: Defer: Resource cleanup in C with GCCs magic

#47
post #32

Just use C++, it's its main feature on top of C.

> on top of C. If we're referring to the "C is a subset of C++" / "C++ is a superset of C" idea, then this just hasn't been the case for some time now, and the two continue to diverge. It came up recently, so I'll link to a previous comment on it ( https://news.ycombinator.com/item?id=45268696 ). I did reply to that with a few of the other current/future ways C is proposing/going to diverge even further from C++, sin…

> But C++ still can't be used in many places that C is

Unless we are speaking about PICs or similar old school 8 and 16 bit CPUs, with compilers like those from MIKROE, there is hardly a platform left were the vendor compiler isn't C and C++ (even if it doesn't go beyond C++11).

And if it must be deployed as freestanding, there are still enough improvements to take advantage of.

In the end it boils down to human factor in most cases, however as Dan Saks puts "If you're arguing, you're losing.", taken from

CppCon 2016: “extern c: Talking to C Programmers about C++”

https://www.youtube.com/watch?v=D7Sd8A6_fYU

Re: Defer: Resource cleanup in C with GCCs magic

#48
post #32

Just use C++, it's its main feature on top of C.

> on top of C. If we're referring to the "C is a subset of C++" / "C++ is a superset of C" idea, then this just hasn't been the case for some time now, and the two continue to diverge. It came up recently, so I'll link to a previous comment on it ( https://news.ycombinator.com/item?id=45268696 ). I did reply to that with a few of the other current/future ways C is proposing/going to diverge even further from C++, sin…

> this just hasn't been the case for some time now

Which I find sad actually. The idea of C++ as a superset of C is really powerful, especially when mixing C and C++. A while ago I had a C project (firmware for a microcontroller) and wanted to bake the version and the compilation time into the firmware. I didn't find a way to do this in plain C, but in C++ you can initialize a global struct and it gets statically linked into the output. This didn't even use constexpr, just preprocessor trickery. Then it was just a matter of renaming the c file to cpp and recompiling. I guess you could also do that with C, but there are things like RAII or constexpr or consuming a C++ library that you can't do without.

Re: Defer: Resource cleanup in C with GCCs magic

#49
post #36
post #33

Earlier quoted context omitted.

If «ptr» is not a valid pointer, an attempt to dereference it (i.e. *ptr) will most assuredly crash the process with a SIGSEGV.

But when would it not be a valid pointer, and yet also not a null pointer? A null pointer we can check for easily.

A null pointer is not a valid pointer in a predominant number of systems in existence. If malloc (3) has returned a NULL, *ptr will cause a SIGSEGV.

Embedded systems are an exception, though. They may not have a MMU, and in such a case the operation will succeed.

Re: Defer: Resource cleanup in C with GCCs magic

#50

I don't understand why people insist on simulating a poor substitute for RAII with a feature that is itself almost decent RAII. > If malloc fails and returns NULL, the cleanup function will still be called, and there’s no simple way to add a guard inside free_ptr. free(NULL) is a no-op, this is a non-issue. I don't know what's so hard about a single if statement anyway even if this were an issue.

Not having RAII is precisely the reason I prefer C over C++ or Rust. I WANT to be able to separate allocation from initialization. I'm currently working with Arduino code and the API is a mess. Everything has a second set of manual constructor/destructor, which bypasses type-safety entirely. All only to shoehorn having existing, but uninitialized objects into C++.

> I WANT to be able to separate allocation from initialization.

Which hardly ever makes sense, and is possible with clean C++ anyway...

Post reply on HN