can realloc move pointer if new size smaller?
Asked Answered
W

6

13

I am wondering whether the C or C++ standard guarantees that a pointer is not changed when realloc is called with a smaller (nonzero) size:

size_t n=1000;
T*ptr=(T*)malloc(n*sizeof(T));
//<--do something useful (that won't touch/reallocate ptr of course)
size_t n2=100;//or any value in [1,n-1]
T*ptr2=(T*)realloc(ptr,n2*sizeof(T));
//<-- are we guaranteed that ptr2==ptr ?

Basically, can the OS decide on its own that since we freed a large memory block, he wants to take advantage of all reallocs to defragment the memory, and somehow move ptr2 ?

Warram answered 15/11, 2009 at 3:11 Comment(1)
Just checked on two Linux-boxes (64 bit, glibc-2.17 and 2.19): even with the same size, realloc does move the block.Amphisbaena
J
17

http://opengroup.org/onlinepubs/007908775/xsh/realloc.html

Upon successful completion with a size not equal to 0, realloc() returns a pointer to the (possibly moved) allocated space.

Nope, no guarantee

Jennajenne answered 15/11, 2009 at 3:14 Comment(2)
Earlier on that page, it says "The realloc() function changes the size of the memory object pointed to by ptr to the size specified by size. The contents of the object will remain unchanged up to the lesser of the new and old sizes. If the new size of the memory object would require movement of the object, the space for the previous instantiation of the object is freed." It doesn't rule out motion, but it is relatively unlikely.Klopstock
Yes, you are still guaranteed that whatever was in memory before would still be there, thanks for pointing that outJennajenne
M
8

There's no guarantee realloc will return the same location, period.

Minatory answered 15/11, 2009 at 3:16 Comment(5)
It would be nice if this was definitively stated somewhere. Not saying that "X is guaranteed to happen" is not the same as specifically stating that "X is not guaranteed to happen".Libenson
@Libenson Yes, it actually is. Not specifying guarantees means no guarantees.Broeder
@Broeder I see your point, but it would still be nice to see it definitively stated somewhere, e.g. in a book, if not in the documentation. From the user's perspective, not being able to find a guarantee means that either there is none, or they have looked in the wrong place.Libenson
@Libenson If it's not stated in the standard, then you can write a conforming implementation without that guarantee. So if the standard does not demand it, you cannot expect it from implementations in general. Of course you can still write an implementation that has this guarantee, because it would not violate the standard. So look in the standard or in the documentation for a specific implementation. But it really is as simple as since the standard does not require it, the guarantee does not exist in the general case.Broeder
@Libenson Also, wanting such evidence is a bit like Russell's teapot.Broeder
M
6

With realloc, you get absolutely no guarantees about where the memory will live afterwords. I believe that libc's default malloc will only begrudgingly copy memory around, so practically speaking you may be OK. But don't count on it.

Menam answered 15/11, 2009 at 3:13 Comment(0)
O
5

realloc is not required to leave the block in place even if it would fit, and in fact the simplest stub implementation is an example where it might not:

  • malloc: call sbrk.
  • realloc: call malloc and memcpy.
  • free: no-op.

This may sound ridiculous, but sometimes for embedded systems an implementation like I've just described is actually the optimal one.

Osset answered 22/9, 2010 at 5:3 Comment(2)
Another example is an implementation where all adjacent allocations are blocks of the same size in order to avoid fragmentation. In that case, a 32-byte block no longer belongs in the same location as the former 4096-byte block.Brickwork
Yes. Another more advanced example would be an implementation which examines whether the left-hand neighbor of the block to be shrunk is free, whether a significant free block will be created on the right-hand side by shrinking, whether the resulting size is "small enough" that memcpy is not too expensive... and if the right conditions are met, moves the the block to a new location to avoid fragmentation.Osset
H
3

It seems to me that all the current answers (at the time of this answer) do not refer to any standard document.

For C++ I will refer to Working Draft, Standard for Programming Language C++, Document Number: N3337, Date: 2012-01-16, Revises: N3291 that, according to https://isocpp.org/std/the-standard, is the closest free document to the non-free official C++11 standard document; here we find at 20.6.13 C library:

2 The contents are the same as the Standard C library header , with the following changes:[in my opinion the listed changes are not relevant to the question].

So now we have to refer to the C standard.

According to https://mcmap.net/q/17216/-where-do-i-find-the-current-c-or-c-standard-documents the closest free document to the non-free official C11 standard document is Programming languages — C, N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x; here we find at 7.22.3.5 The realloc function:

4 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.

I am not a native English speaker and so is up to you to interpret the meaning of "may have".

Hiss answered 4/8, 2014 at 18:13 Comment(1)
I am a native English speaker (and quite familiar with the C standard). The quoted text says that new pointer may or may not have the same value as the old pointer, with no implication that this depends on the size. A rationale (not stated in the standard) is that an implementation could allocate a smaller chunk in a different location to reduce fragmentation and make future allocations more likely to succeed. For there to be a guarantee that it's not moved in some cases, that would have to be stated explicitly in the standard. It isn't.Credenza
E
0

On Windows, the C-Runtime grabs a heap, and then allocates memory from that heap. So the OS won't know about individual memory allocations, and thus won't move things around.

Expressivity answered 15/11, 2009 at 3:15 Comment(2)
This is not correct. The Visual C run-time does not directly call the OS heap implementation, for one thing. For another, the HeapReAlloc() call does move things around.Indoor
You need to double check your docs. See: msdn.microsoft.com/en-us/library/csd157zx.aspx The CRT grabs a single OS heap to use internally. It then sub-allocates that heap (meaning it doesn't use the Win32 heap calls to do allocations within that heap)Expressivity

© 2022 - 2024 — McMap. All rights reserved.