CHECK_MALLOC is an anti-pattern (do you have CHECK_FOO for any given FOO which might behind the scenes allocate?).
I have a litany of reasons why you shouldn't bother checking malloc returns, and instead invest a little effort in making sure your platform malloc is configured to abort instead of returning NULL. The simplest and most compelling of those reasons is that it's easier and cleaner.
I'm also not a fan of a macro that introduces an implicit dependency on a goto label.
do { } while(0)
is a pretty convenient way of expressing single-return; you just use "break" instead of "return".
I can accept (most of) your issue(s) with the MALLOC macro, MALLOC is a bad name here from previous habit. The point was that there's code one has no control over which indicates failure by returning a NULL values, this is where it's generally useful.
I strongly disagree about the goto label. "break" is not equivalent (consider a nested for/while/switch). Plus, it's not "implicit" if it's well-known and oft-used in the code in question.
You strongly disagree about something I don't strongly disagree about. I wouldn't use goto to get single-return, nor would I wrap drastic control flow in a macro, but whatever floats your boat.
I have much stronger opinions about checking malloc. It's something people spend a lot of effort to do that actually makes their code worse.
Would your opinions on checking malloc still hold if the system in question were an embedded system that should continue operating with partial functionality even when out of memory? Also, when you say "makes their code worse," are you saying harder to read, harder to debug, less secure, slower, buggier, or all of the above?
My habit of checking malloc() also comes from my distaste for audio software that randomly displays erratic behavior when memory starts getting tight, rather than displaying an alert that an allocation failed.
I think you can always find exceptions -- such is engineering. :-)
In my example above, one of the things I also failed to clarify about that test was that it was in the context of a system that could back off and restart or the call was returning NULL for reasons other than OOM. But like I said, we rigged malloc() to blow, because malloc() is the generic purpose allocator, and you're screwed if that goes.
I think tp gives good advice here: for your typical malloc() user, you're usually screwed if malloc returns NULL, because that's your heap allocator, and you have nothing else :-)
An embedded system, generally, will have a great deal more knowledge of how to back off -- in other words, the memory allocator is something that is under much more control -- it probably isn't malloc()...
Your boat will sink if you use do while break. I know, I've tried. :-) One aspect I failed to highlight is the logging the macro does, which can come in handy.
I wish I could erase the MALLOC thing, it was an after-thought ... and now I feel like I'm leading people astray (oh well...). Even in the code that used it, it was for a existing calls that returned NULL instead of an rc. malloc() was rigged to blow in that code base. Sigh...
I have a litany of reasons why you shouldn't bother checking malloc returns, and instead invest a little effort in making sure your platform malloc is configured to abort instead of returning NULL. The simplest and most compelling of those reasons is that it's easier and cleaner.
I'm also not a fan of a macro that introduces an implicit dependency on a goto label.
is a pretty convenient way of expressing single-return; you just use "break" instead of "return".