Using realloc to shrink the allocated memory
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:
- The implementation splits the allocated memory block at the new requested length and frees the unused portion at the end.
- The implementation makes a new allocation with the new size, copies the old contents to the new location, and frees the entire old allocation.
- 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;
Admin
Updated on July 25, 2020Comments
-
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 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 almost 13 yearsSteve 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 torealloc(x,0)
. -
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 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 almost 13 yearsWhat 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 almost 13 yearsSuppose 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 almost 13 yearsNote 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 almost 13 yearsPOSIX 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 almost 13 yearsAh 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 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 almost 13 yearsThe 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 over 10 yearsRealloc will still leak. This is the correct answer. At least on windows 7, 64 bit (tdm-gcc64)
-
dns over 10 yearsThis is not the correct answer, the realloc will still leak. Please read the azphare & Jens Gustedt for correct answer.
-
csavvy over 4 yearsSorry 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 over 2 yearsThank 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).