liveBook · Manning

Realloc

As explained in Modern C, Third Edition

realloc is a C library function that changes the size of an allocated storage region while preserving its existing contents up to the applicable size.

Growing a circular buffer

A resize can begin with `double* ntab = realloc(c->tab, sizeof(double[nlen]));` followed by `if (!ntab) return nullptr;`. The call supplies the existing allocation and its requested new size. Keeping the result in `ntab` lets the code check for failure before replacing the stored pointer. section 13.1.1

`realloc`, declared in `<stdlib.h>`, grows or shrinks dynamically allocated storage. It returns a pointer to the resized object or null on failure. A null input pointer makes it allocate storage like `malloc`. Use a size strictly greater than zero. section 13.1 section 13.1.1

A successful call changes which pointer is valid:

  • The returned address may equal the old address, or the runtime may provide a different object. Even when the addresses match, pointers derived from the original object become invalid. section 13.1.1
  • Existing contents are preserved up to the applicable size: growth retains the old initial portion; shrinkage retains the initial portion that fits. section 13.1.1
  • Do not separately free the old object after a successful relocation. `realloc` takes care of it while providing the new object. section 13.1.1 section 13.1.2

TAKEAWAY: Check the new pointer before replacing the old one. A failed attempt to enlarge a printing buffer takes a cleanup path that frees the original buffer; overwriting its only pointer with the null result would lose that path to cleanup. Eventually, free a retained allocation using a pointer returned by an allocation function, not an interior pointer or one already freed. section 15.6 section 13.1.2

Listing 15.2 Printing an array of numbers, optimized version
int fprintnumbers_opt(FILE*restrict stream,
                  char const form[restrict static 1],
                  char const sep[restrict static 1],
                  size_t len, size_t nums[restrict static len]) {
  if (!stream)       return -EFAULT;
  if (len && !nums)  return -EFAULT;
  if (len > INT_MAX) return -EOVERFLOW;

  int err = errno;
  size_t const seplen = strlen(sep);

  size_t tot = 0;
  size_t mtot = len*(seplen+10);
  char* buf = malloc(mtot);

  if (!buf) return error_cleanup(ENOMEM, err);

  for (size_t i = 0; i < len; ++i) {
    tot += sprintf(&buf[tot], form, nums[i]);
    ++i;
    if (i >= len) break;
    if (tot > mtot-20) {
      mtot *= 2;
      char* nbuf = realloc(buf, mtot);
      if (nbuf) {
        buf = nbuf;
      } else {
        tot = error_cleanup(ENOMEM, err);
        goto CLEANUP;
      }
    }
    memcpy(&buf[tot], sep, seplen);
    tot += seplen;
    if (tot > INT_MAX) {
      tot = error_cleanup(EOVERFLOW, err);
      goto CLEANUP;
    }
  }
  buf[tot] = 0;

  /* print whole line in one go */
  if (fputs(buf, stream) == EOF) tot = EOF;
 CLEANUP:
  free(buf);
  return tot;
}

The optimized number-printing listing keeps `buf` while trying `realloc(buf, mtot)`, assigns the result only when it is non-null, and jumps to cleanup otherwise. section 15.6

How Modern C, Third Edition covers it

How deep it goes
Explains return values, relocation, preserved contents, pointer invalidation, and failure cleanup, without prescribing how the runtime chooses an address.
Examples
Uses circular-buffer growth and an optimized number-printing buffer that doubles its capacity.
What it assumes
Assumes working knowledge of C pointers, arrays, and size calculations while supplying the allocation-function declarations.
What you can do after
Build it from scratch: resize an allocated buffer, check failure before replacing its pointer, and arrange cleanup.
How it connects
Connects realloc to malloc, free, dynamic allocation, pointer validity, memory leaks, and error handling.

Also explained in

Compare how 2 books explain realloc →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Modern C, Third Edition. The section links point to the parts of the book it draws on.