Recall assert() is normally only active in debug build of programs and not release versions.
Classify the potential errors into groups:
1) Run-time errors that must be handled.
assert() is no good here, instead code must handle the error.
2) Run-time errors that should be handled yet have no defined remedy.
assert() is not wise here either. Code should signal (leave error message) and exit.
3) Run-time errors with no simply re-course to handle them.
assert() could be used here. Now when the program faults/dies/hangs we are left with nothing. Recommend code should signal like in #2 if at all possible.
4) Compile time errors.
assert(sizeof(int)*CHAR_BIT >= 32) is a good example usage. It is reasonable to assume that a build will occur in debug mode. Even this carries a risk with deployed source code that a user in the field may skip the debug build, so suggest only use assert() for internal code.
assert() is a tool in the C toolbox. It has its uses - and mis-uses.
With malloc(), I have worked on many projects that barred direct use of C lib malloc() and instead used a project specific code like my_malloc_never_fail() and my_malloc_may_fail() which had error handling and metrics. As @Weather Vane commented, good error handle is challenging.