Using realloc to shrink the allocated memory

33,304

Solution 1

No, you won't have a memory leak. realloc will simply mark the rest "available" for future malloc operations.

But you still have to free myPointer later on. As an aside, if you use 0 as the size in realloc, it will have the same effect as free on some implementations. As Steve Jessop and R.. said in the comments, you shouldn't rely on it.

Solution 2

There is definitely not a memory leak, but any of at least 3 things could happen when you call realloc to reduce the size:

  1. The implementation splits the allocated memory block at the new requested length and frees the unused portion at the end.
  2. The implementation makes a new allocation with the new size, copies the old contents to the new location, and frees the entire old allocation.
  3. The implementation does nothing at all.

Option 3 would be a rather bad implementation, but perfectly legal; there's still no "memory leak" because the whole thing will still be freed if you later call free on it.

As for options 1 and 2, which is better depends a lot on whether you favor performance or avoiding memory fragmentation. I believe most real-world implementations will lean towards doing option 1.

Solution 3

The new code still leaks the original allocation if the realloc fails. I expect most implementations won't ever fail to shrink a block, but it's allowed. The correct way to call realloc, whether growing or shrinking the block, is void *tmp = realloc(myPointer, 50*sizeof(int)); if (!tmp) { /* handle error somehow. myPointer still points to the old block, which is still allocated */ } myPointer = tmp;. – Steve Jessop 48 mins ago

Hey, I couldn't figure out how to reply to your comment, sorry.

Do I need to cast tmp to the type of myPointer? In this case, do I need to write

myPointer = (int*)tmp

Also, in this case, when I do free(myPointer) The memory pointed at by tmp will be freed as well, right? So no need to do

free(myPointer)
free(tmp)

Solution 4

In the way you have given your code, yes, it might have a leak. The idea of realloc is that it can return you a new location of your data. Like you do it in your question you lose that pointer that realloc sends you.

int *myPointer2 = realloc(myPointer,50*sizeof(int));
assert(myPointer2); 
myPointer = myPointer2;
Share:
33,304
Admin
Author by

Admin

Updated on July 25, 2020

Comments

  • Admin
    Admin almost 4 years

    Simple question about the realloc function in C: If I use realloc to shrink the memory block that a pointer is pointing to, does the "extra" memory get freed? Or does it need to be freed manually somehow?

    For example, if I do

    int *myPointer = malloc(100*sizeof(int));
    myPointer = realloc(myPointer,50*sizeof(int));
    free(myPointer);
    

    Will I have a memory leak?

  • Steve Jessop
    Steve Jessop almost 13 years
    "if you use 0 as the size in realloc, it will have the same effect as free." - might be true in your implementation, but not guaranteed. If realloc returns a null pointer from a 0 input, and did not set errno to ENOMEM, then the memory was freed. But just like malloc, realloc is allowed to attempt to return an actual allocation of 0 usable size. The implementation is required to document which (7.20.3/1).
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE almost 13 years
    Steve is right, and the practical consequence of this is that you should just never call realloc with a size of 0. Dealing with all the possible behaviors, the existence of non-conformant implementations, and the fact that the C and POSIX folks seem to disagree on what's conformant and what's not makes it a very bad idea to rely on anything related to realloc(x,0).
  • cnicutar
    cnicutar almost 13 years
    @Steve Jessop, R.. Thank you for clarifying :-) I never bothered to check beyond POSIX, I didn't know it's non-C-standard.
  • Steve Jessop
    Steve Jessop almost 13 years
    @cnicutar: Posix also permits actual 0-sized allocations. I don't know what disagrement R.. refers to, but it must be a difference in interpretation of the C standard, because it's not as simple as Posix just restricting the allowed behavior.
  • Harsh Pathak
    Harsh Pathak almost 13 years
    What is the reasoning behind option 2 when you need to reduce the allocated memory? I can't figure it out.
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE almost 13 years
    Suppose you allocated 100 bytes and want to resize down to 50 bytes. The first allocation claimed a 100-byte free zone, and option 1 gives back a 50-byte free zone, but the longer 100-byte zone is no longer available. If, however, there were another free zone that's only 50 bytes long, option 2 could move the data to that location and free up a 100-byte zone, leaving memory less fragmented.
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE almost 13 years
    Note that if your goal is to optimize for minimal fragmentation, it only makes sense to take option 2 when a smaller free zone large enough to contain the allocation already exists. If you have to get more memory from the system or split another larger free zone, it can only make fragmentation worse, not better.
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE almost 13 years
    POSIX says "If size is 0 and ptr is not a null pointer, the object pointed to is freed." ISO C does not make this requirement, and in fact, if the implementation takes the option of having malloc(0) return a unique pointer rather than NULL, it seems to contradict the C requirements. It's all sufficiently confusing I don't think apps should even try to deal with it, but just steer clear of the nonsense...
  • Harsh Pathak
    Harsh Pathak almost 13 years
    Ah I see ; so we minimize fragmentation at the expense of the time taken to allocate a new block, and copy data. Also, I suppose there's no way to control such behavior?
  • Jens Gustedt
    Jens Gustedt almost 13 years
    @R.. actually I was not so sure, that's why I didn't just put it in a comment. If you think of it, they way he really asked his question it is much more natural to wonder what happens to the "spare" memory.
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE almost 13 years
    The best way to control such behavior is to allocate what you need rather than over-allocating and resizing. I'm not aware of whether any implementations actually take option 2, but it's probably a good idea, especially since it would only affect relatively small allocations where the cost of copying is low. (On a modern OS, large allocations are managed directly by the kernel and can be relocated to new addresses with contiguous space via virtual memory remappings.)
  • dns
    dns over 10 years
    Realloc will still leak. This is the correct answer. At least on windows 7, 64 bit (tdm-gcc64)
  • dns
    dns over 10 years
    This is not the correct answer, the realloc will still leak. Please read the azphare & Jens Gustedt for correct answer.
  • csavvy
    csavvy over 4 years
    Sorry to write on 8 year old topic, but I just wanted to know if I shrink the size from 100 to 50, only the first fifty bytes(0-49) will be copied to new pointer, but what if I want to copy some random 50 bytes from 100 bytes, is there a standard procedure for that or I will have to allocate separate 50 bytes first (ex: malloc(50)) , then copy required data and free previous pointer?
  • User 10482
    User 10482 over 2 years
    Thank you @SteveJessop for the clarification. From cppreference the behavior of realloc with size 0 was changed from c++98 to c++11. It was freed before but standard doesn't explicitly guarantee that anymore (just talks about return value).