Re: "Then calloc() returns an error"
For typical PC code I use a version of the NR vector() function that calls calloc() AND checks the return, forcing a ext if it fails after logging that numbers that triggered the failure. That way my code is neater than lots of in-line tests, etc.
I know there are cases when you want to continue and try a different value, but in most cases if you run out of allocatable memory it is game over for your original planned execution anyway.
Other languages have ways to trap stuff that don't relay on a function wrapper, but equally mine can have a brutal #define vector calloc used if I want simplified code for embedded stuff.