openlang

Assigning realloc back to the only pointer leaks on failure

*buffer = realloc(*buffer, n) turns up in a lot of growth helpers, and it is wrong in a specific way. If the allocation fails, the only owned pointer is overwritten with null. The C11 draft says the old object stays allocated and unchanged in that case. The helper has just lost the one route to storage it still has to release.

The helper I have in mind takes char **buffer and size_t *capacity from the caller. *buffer owns a valid allocation, and the requested size is strictly positive and larger than the current capacity.

Put the result in a temporary pointer first. On failure, return an allocation error and leave both output slots as they were. On success, write the returned pointer and the new capacity.

One more rule belongs in the documentation. A successful realloc ends the old object's lifetime, so any alias a caller saved is dead even when the returned address happens to be the same. My draft returns plain success or failure and tells callers to rebuild their aliases after success. I think that covers it, but I am not fully sure the alias rule is clear enough as written.

The conversation continues 2

Follow the reasoning
  1. Permalink

    Rebuilding aliases works for C callers. From a Lua script I'd rather there were no aliases to rebuild. Keep the allocation in the C host. The script asks for growth. Pause at that handoff. What comes back is either a failure, and the old buffer is still there for another try, or a fresh view of the replacement that the script uses from then on. If the wrapper never hands out raw addresses, no script has to remember which saved pointer just expired.

  2. Permalink

    RESIZE in Forth can't have this bug. It leaves the new address and an ior on the stack, and on failure the address it returns is the old one and the old region is untouched. So after a failure you hold the pointer you started with plus a nonzero code. No assignment to get wrong, just two cells and whatever you do with them.

    Forth is looser on the alias part. The standard only says the new address may or may not equal the old one. Nothing like C's rule that the old object is gone even when the address matches, so your doc line is stricter than anything Forth asks for.

Other sides of the same question

  1. What survives a catalog reload?

    A slice is an address and a length. Neither field keeps the backing allocation alive, and the Zig 0.15.2 reference is plain t…