12

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 ?

spirov
  • 261
  • 4
  • 6

6 Answers6

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

Jeffrey Aylesworth
  • 8,242
  • 9
  • 40
  • 57
  • 1
    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. – Jonathan Leffler Nov 15 '09 at 05:30
  • 1
    Yes, you are still guaranteed that whatever was in memory before would still be there, thanks for pointing that out – Jeffrey Aylesworth Nov 15 '09 at 15:19
8

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

Jim Zajkowski
  • 987
  • 1
  • 7
  • 13
  • 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". – RoG Dec 16 '16 at 11:58
  • 2
    @RoG Yes, it actually is. Not specifying guarantees means no guarantees. – klutt Jul 07 '20 at 23:53
  • @klutt 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. – RoG Jul 09 '20 at 09:26
  • 1
    @RoG 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. – klutt Jul 09 '20 at 12:46
  • @RoG Also, wanting such evidence is a bit like [Russell's teapot](https://en.wikipedia.org/wiki/Russell%27s_teapot). – klutt Jul 09 '20 at 12:50
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.

zenazn
  • 14,295
  • 2
  • 36
  • 26
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.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 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. – Zan Lynx May 11 '11 at 21:01
  • 2
    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. – R.. GitHub STOP HELPING ICE May 11 '11 at 22:41
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://stackoverflow.com/a/83763/15485 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".

Community
  • 1
  • 1
Alessandro Jacopson
  • 18,047
  • 15
  • 98
  • 153
  • 6
    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. – Keith Thompson Aug 04 '14 at 19:09
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.

DougN
  • 4,407
  • 11
  • 56
  • 81
  • 1
    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. – Heath Hunnicutt Nov 15 '09 at 03:18
  • 1
    You need to double check your docs. See: http://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) – DougN Nov 16 '09 at 14:54