Skip to content

Instantly share code, notes, and snippets.

@sw17ch
Last active May 20, 2020 13:45
Show Gist options
  • Select an option

  • Save sw17ch/7100909 to your computer and use it in GitHub Desktop.

Select an option

Save sw17ch/7100909 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#define IGNORE(X) ((void)X)
#define MAX_ALLOC (1024 * 1024)
#define MIN_ALLOC (128)
int main(int argc, char * argv[]) {
IGNORE(argc);
IGNORE(argv);
void * ptr = malloc(MIN_ALLOC);
for (int i = 0; i < 100; i++) {
size_t realloc_sz = arc4random_uniform(MAX_ALLOC);
void * new_ptr = realloc(ptr, realloc_sz);
if (NULL == new_ptr) {
printf("Realloc of size: %lu. Realloc failed!\n", realloc_sz);
} else if (new_ptr != ptr) {
printf("Realloc of size: %lu. Pointer changed: (%p -> %p)\n", realloc_sz, ptr, new_ptr);
ptr = new_ptr;
} else {
printf("Realloc of size: %lu. Pointer is the same: (%p)\n", realloc_sz, ptr);
}
}
return 0;
}
@sw17ch

sw17ch commented Oct 22, 2013

Copy link
Copy Markdown
Author

Example output on my machine.

Realloc of size: 110564. Pointer changed: (0x7fb230403a40 -> 0x7fb230803200)
Realloc of size: 202928. Pointer changed: (0x7fb230803200 -> 0x108e74000)
Realloc of size: 498876. Pointer changed: (0x108e74000 -> 0x108ea7000)
Realloc of size: 654595. Pointer is the same: (0x108ea7000)
Realloc of size: 324896. Pointer is the same: (0x108ea7000)
Realloc of size: 756332. Pointer is the same: (0x108ea7000)
Realloc of size: 331883. Pointer is the same: (0x108ea7000)
Realloc of size: 790188. Pointer is the same: (0x108ea7000)
Realloc of size: 537938. Pointer is the same: (0x108ea7000)
Realloc of size: 117893. Pointer changed: (0x108ea7000 -> 0x7fb23081f200)
Realloc of size: 645305. Pointer changed: (0x7fb23081f200 -> 0x108ea7000)
Realloc of size: 133888. Pointer is the same: (0x108ea7000)
Realloc of size: 374731. Pointer is the same: (0x108ea7000)
Realloc of size: 438182. Pointer is the same: (0x108ea7000)
Realloc of size: 693929. Pointer is the same: (0x108ea7000)
Realloc of size: 34714. Pointer changed: (0x108ea7000 -> 0x7fb230803200)
Realloc of size: 163268. Pointer changed: (0x7fb230803200 -> 0x108e74000)
Realloc of size: 759683. Pointer changed: (0x108e74000 -> 0x108f51000)
Realloc of size: 380807. Pointer is the same: (0x108f51000)
Realloc of size: 773858. Pointer is the same: (0x108f51000)
Realloc of size: 496886. Pointer is the same: (0x108f51000)
Realloc of size: 972229. Pointer is the same: (0x108f51000)
Realloc of size: 247466. Pointer is the same: (0x108f51000)
Realloc of size: 704663. Pointer is the same: (0x108f51000)
Realloc of size: 477820. Pointer is the same: (0x108f51000)
Realloc of size: 324535. Pointer is the same: (0x108f51000)
Realloc of size: 652925. Pointer is the same: (0x108f51000)
Realloc of size: 680301. Pointer is the same: (0x108f51000)
Realloc of size: 826933. Pointer is the same: (0x108f51000)
Realloc of size: 845945. Pointer is the same: (0x108f51000)
Realloc of size: 298718. Pointer is the same: (0x108f51000)
Realloc of size: 285273. Pointer is the same: (0x108f51000)
Realloc of size: 739287. Pointer is the same: (0x108f51000)
Realloc of size: 229793. Pointer is the same: (0x108f51000)
Realloc of size: 332791. Pointer is the same: (0x108f51000)
Realloc of size: 304355. Pointer is the same: (0x108f51000)
Realloc of size: 318195. Pointer is the same: (0x108f51000)
Realloc of size: 493145. Pointer is the same: (0x108f51000)
Realloc of size: 705298. Pointer is the same: (0x108f51000)
Realloc of size: 122644. Pointer changed: (0x108f51000 -> 0x7fb23083c000)
Realloc of size: 806343. Pointer changed: (0x7fb23083c000 -> 0x108ffe000)
Realloc of size: 58574. Pointer changed: (0x108ffe000 -> 0x7fb230803200)
Realloc of size: 964268. Pointer changed: (0x7fb230803200 -> 0x1090c3000)
Realloc of size: 602853. Pointer is the same: (0x1090c3000)
Realloc of size: 468643. Pointer is the same: (0x1090c3000)
Realloc of size: 473259. Pointer is the same: (0x1090c3000)
Realloc of size: 102301. Pointer changed: (0x1090c3000 -> 0x7fb23081f200)
Realloc of size: 432489. Pointer changed: (0x7fb23081f200 -> 0x1090c3000)
Realloc of size: 126028. Pointer changed: (0x1090c3000 -> 0x7fb230838200)
Realloc of size: 599311. Pointer changed: (0x7fb230838200 -> 0x108ea7000)
Realloc of size: 476167. Pointer is the same: (0x108ea7000)
Realloc of size: 716273. Pointer changed: (0x108ea7000 -> 0x108ffe000)
Realloc of size: 684132. Pointer is the same: (0x108ffe000)
Realloc of size: 427621. Pointer is the same: (0x108ffe000)
Realloc of size: 431543. Pointer is the same: (0x108ffe000)
Realloc of size: 2310. Pointer changed: (0x108ffe000 -> 0x7fb230857000)
Realloc of size: 938069. Pointer changed: (0x7fb230857000 -> 0x109137000)
Realloc of size: 142082. Pointer is the same: (0x109137000)
Realloc of size: 548221. Pointer is the same: (0x109137000)
Realloc of size: 520596. Pointer is the same: (0x109137000)
Realloc of size: 105870. Pointer changed: (0x109137000 -> 0x7fb230803200)
Realloc of size: 478956. Pointer changed: (0x7fb230803200 -> 0x109137000)
Realloc of size: 542945. Pointer is the same: (0x109137000)
Realloc of size: 801501. Pointer is the same: (0x109137000)
Realloc of size: 581633. Pointer is the same: (0x109137000)
Realloc of size: 354941. Pointer is the same: (0x109137000)
Realloc of size: 806944. Pointer is the same: (0x109137000)
Realloc of size: 925705. Pointer is the same: (0x109137000)
Realloc of size: 239300. Pointer is the same: (0x109137000)
Realloc of size: 360228. Pointer is the same: (0x109137000)
Realloc of size: 251701. Pointer is the same: (0x109137000)
Realloc of size: 695012. Pointer is the same: (0x109137000)
Realloc of size: 114834. Pointer changed: (0x109137000 -> 0x7fb23081f200)
Realloc of size: 190479. Pointer changed: (0x7fb23081f200 -> 0x108e74000)
Realloc of size: 271218. Pointer changed: (0x108e74000 -> 0x1090c3000)
Realloc of size: 323535. Pointer is the same: (0x1090c3000)
Realloc of size: 709850. Pointer changed: (0x1090c3000 -> 0x108ffe000)
Realloc of size: 296373. Pointer is the same: (0x108ffe000)
Realloc of size: 591498. Pointer is the same: (0x108ffe000)
Realloc of size: 272498. Pointer is the same: (0x108ffe000)
Realloc of size: 546381. Pointer is the same: (0x108ffe000)
Realloc of size: 789159. Pointer is the same: (0x108ffe000)
Realloc of size: 386675. Pointer is the same: (0x108ffe000)
Realloc of size: 98840. Pointer changed: (0x108ffe000 -> 0x7fb230803200)
Realloc of size: 398230. Pointer changed: (0x7fb230803200 -> 0x109137000)
Realloc of size: 290881. Pointer is the same: (0x109137000)
Realloc of size: 400433. Pointer is the same: (0x109137000)
Realloc of size: 300580. Pointer is the same: (0x109137000)
Realloc of size: 216870. Pointer is the same: (0x109137000)
Realloc of size: 158205. Pointer is the same: (0x109137000)
Realloc of size: 724029. Pointer is the same: (0x109137000)
Realloc of size: 767720. Pointer is the same: (0x109137000)
Realloc of size: 512054. Pointer is the same: (0x109137000)
Realloc of size: 165563. Pointer is the same: (0x109137000)
Realloc of size: 645002. Pointer is the same: (0x109137000)
Realloc of size: 696562. Pointer is the same: (0x109137000)
Realloc of size: 851076. Pointer is the same: (0x109137000)
Realloc of size: 365941. Pointer is the same: (0x109137000)
Realloc of size: 581421. Pointer is the same: (0x109137000)
Realloc of size: 456283. Pointer is the same: (0x109137000)

@telemachus

Copy link
Copy Markdown

So this makes me wonder again about leaks.

If at the end of the program, after the loop, I free ptr and new_ptr, I'm freeing 0x109137000 (new_ptr) and 0x7fb230803200 (ptr). Aren't the other pointer addresses abandoned but never freed? (I.e. aren't they left unhandled?)

@silentbicycle

Copy link
Copy Markdown

Read the man page closely for realloc, and/or the C standard. The OpenBSD man page is particularly good about documenting realloc's edge cases: http://www.openbsd.org/cgi-bin/man.cgi?query=realloc

@sw17ch

sw17ch commented Oct 22, 2013

Copy link
Copy Markdown
Author

Good question. From man realloc:

If there is not enough room to enlarge the memory allocation pointed to by ptr, realloc() creates a new allocation, copies as much of the old data pointed to by ptr as will fit to the new allocation, frees the old allocation, and returns a pointer to the allocated memory.

Happily, realloc takes care of that free for you. The only case where the original pointer passed to realloc should ever be used again is if realloc returns NULL (indicating a failure).

Here's a naive example of what happens inside realloc. Note: this implementation assumes that size is greater-than-or-equal-to the original size of ptr. In other words: this implementation is undefined if size is less than the original allocated size of ptr.

void * realloc(void * ptr, size_t size) {
  void * new_ptr = malloc(size);
  memcpy(new_ptr, ptr, size);
  free(ptr);
  return new_ptr;
}

@telemachus

Copy link
Copy Markdown

Thank you both (again)! At some point, I owe you both a beverage of choice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment