For the first item on reference counting, batched memory management is a possible alternative that still fits the C style. The use of something like an arena allocator approximates a memory lifetime, which can be a powerful safety tool. When you free the allocator, all pages are freed at once. Not only is this less error prone, but it can decrease performance. There’s no need to allocate and free each reference counted pointer, nor store reference counts, when one can free the entire allocator after argument parsing is done.
This also decreases fallible error handling: The callee doesn’t need to free anything because the allocator is owned by the caller.
Of course, the use of allocators does not make sense in every setting, but for common lifetimes such as: once per frame, the length of a specific algorithm, or even application scope, it’s an awesome tool!