This seems like a pretty good list.  Focus on error handling is spot-on, most good C is just simply that.<p>One of my favorite tricks is to make your success case and your error cases look largely the same.<p>Say you have N allocations and N things that can fail.  Lots of people get into trouble when they do:<p><pre><code>    void *p, *q, *r, *s;

    p = a();
    if (!p) { return ERROR; }
    q = b();
    if (!q) { free(p); return ERROR; }
    r = c();
    if (!r) { free(p); free(q); return ERROR; }
    &#x2F;&#x2F; etc..
</code></pre>
And this madness just goes on and on.  Add a new allocation?  You potentially have to change n cleanup blocks.<p>I breathe a lot easier when I can do [note we abuse the fact that free(NULL) is a no-op]:<p><pre><code>       void *p = NULL;
       void *q = NULL;
       void *r = NULL;

       p = a();
       if (!p) goto cleanup;
       q = b();
       if (!q) goto cleanup;
       r = c();
       if (!r) goto cleanup;

    cleanup:
       free(p);
       free(q);
       free(r);
</code></pre>
What if the buffer at &quot;r&quot; needs to return something to the caller?  It turns out it&#x27;s really easy to transfer ownership in this pattern:<p><pre><code>       &#x2F;&#x2F; Success case.  Give `r` to the caller.
       *callerPointer = r;
       r = NULL;

       &#x2F;&#x2F; Then we fall through to the failure block...
       &#x2F;&#x2F; r is null now so free(r) is harmless.
    cleanup:
       free(p);
       free(q);
       free(r);</code></pre>