4

I've run into an issue with our code under clang involving realloc. This code works fine under gcc and visual studio, so I'm interested in understanding clang's behavior. Our code does something similar to this (error handling etc elided):

// allocate way more memory than we need
char * memory = malloc(500000);
int memoryused = 0;

// ... code goes here that fills up the memory, keeping track by
// setting memoryused ...

// now we're done, shrink the memory down to the size it needs
memory = realloc(memory, memoryused);

Under gcc and multiple versions of MSVC, the memory pointer wasn't moved. However, under clang, it appears that it moves the memory, even if the size needed is only 1-2000 bytes.

Is there a particular reason that clang does this? The only one I can think of is that perhaps it keeps separate heaps for large and small allocations or something. Otherwise it seems a bit inefficient to move the memory around, when it could just truncate the old memory block and continue using it without having to copy the data at all.

Colen
  • 13,428
  • 21
  • 78
  • 107
  • 1
    By the way, what you're doing is a bad idea. You should _always_ assume that calls to `realloc` can both return a different address _and_ fail (returning NULL), even with reductions, because that's what the standard says. Anything else is just sloppy coding (no offence intended) and your shrink operation is a potential memory leak unless you've saved `memory` somewhere for recovery. See also http://stackoverflow.com/questions/3162502/is-realloc-guaranteed-to-be-in-place-when-the-buffer-is-shrinking/3162534#3162534 for the gory details. – paxdiablo Sep 20 '11 at 06:22
  • Yeah, I figured after running into this problem. Just struck me as weird that it works fine on everything else except clang. :) – Colen Sep 20 '11 at 15:00

1 Answers1

3

I once wondered about this kind of thing as well: Is realloc guaranteed to be in-place when the buffer is shrinking?

To summarise the responses - realloc is allowed to move the buffer around, even when it's just shrinking... The exact details depend on your particular library implementation.

From c99 (emphasis mine):

The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object could not be allocated.

As you've guessed at (and as per some responses in the linked question) some allocators apparently do partition the heap, so that allocations of a particular size range come from the same allocation bucket - preventing heap fragmentation in the case where lots of small objects might otherwise be strewn around, which would stop large contiguous blocks from being allocated.

Hope this helps.

Community
  • 1
  • 1
Darren Engwirda
  • 6,915
  • 4
  • 26
  • 42