What would realloc do if there is no sequential space of memory?
Asked Answered
H

5

13

realloc is used to reallocate the memory dynamically.

Suppose I have allocated 7 bytes using the malloc function and now I want to extend it to 30 bytes.

What will happen in the background if there is no sequential (continously in a single row) space of 30 bytes in the memory?

Is there any error or will memory be allocated in parts?

Hoe answered 10/9, 2010 at 11:36 Comment(0)
L
13

realloc works behind the scenes roughly like this:

  • If there is enough free space behind the current block to fulfill the request, extend the current block and return a pointer to the beginning of the block.
  • Else if there is a large enough free block elsewhere, then allocate that block, copy the data from the old block over, free the old block and return a pointer to the beginning of the new block
  • Else report failure by returning NULL.

So, you can test for failure by testing for NULL, but be aware that you don't overwrite the old pointer too early:

int* p = malloc(x);
/* ... */
p = realloc(p, y); /* WRONG: Old pointer lost if realloc fails: memory leak! */
/* Correct way: */
{
  int* temp = realloc(p, y);
  if (NULL == temp)
  {
    /* Handle error; p is still valid */
  }
  else
  {
    /* p now possibly points to deallocated memory. Overwrite it with the pointer
       to the new block, to start using that */
    p = temp;
  }
}
Lifeless answered 10/9, 2010 at 11:55 Comment(2)
Is this the realloc works for all implementations?Semolina
@CoolGuy: Some implementations might not (be able to) do that first step of extending the current block, but otherwise this is the observable behaviour of realloc for all implementations.Lifeless
L
7

realloc will only succeed if it can return a contiguous ("sequential" in your words) block of memory. If no such block exists, it will return NULL.

Lederhosen answered 10/9, 2010 at 11:38 Comment(6)
@Mark - original memory is left unchanged. A common bug in this context is 'x=realloc(x)' - you have to do 'newX=realloc(x)' to avoid leaking the original x on error.Prosthetics
@Steve Townsend - Thats only when it fails rite? When successful it frees the original pointer. And whos Mark in this page? O_oMotherless
I guess there was an error. First comment was shown from user sharptooth and now its changed though both are addressed to Mark. Was that a bug ? :-PMotherless
@Praveen - my comment was addressed to a now-deleted earlier comment. yes, the usage I showed is still a bug. When successful it frees the original pointer (or returns it to you for use again if contiguous larger block can be anchored there).Prosthetics
@Steve: it's not a bug if you follow it with if (!x) exit(1); :-)Nonappearance
@R - good point. In many apps, I am sure that failure of memory allocation would spell imminent death anyway.Prosthetics
S
1

From the man page:

realloc() returns a pointer to the newly allocated memory, which is suitably aligned for any kind of variable and may be different from ptr, or NULL if the request fails.

So in other words, to detect failure, just check whether the result was NULL.

EDIT: As noted in the comment, if the call fails, the original memory isn't freed.

Subreption answered 10/9, 2010 at 11:38 Comment(1)
Worthwhile to note from the man page: If realloc() fails the original block is left untouched; it is not freed or moved.Plagiary
D
1

In general, it depends on the implementation. On x86(-64) Linux, I believe the standard doug lea malloc algorithm will always allocate a minimum of a standard x86 page (4096 bytes) so for the scenario you described above, it would just reset the boundaries to accomodate the extra bytes. When it comes to, say, reallocating a buffer of 7bytes to PAGE_SIZE+1 I believe it will try to allocate the next contiguous page if available.

Worth reading the following, if you're developing on Linux:

By default, Linux follows an optimistic memory allocation strategy. This means that when malloc() returns non-NULL there is no guarantee that the memory really is available. This is a really bad bug. In case it turns out that the system is out of memory, one or more processes will be killed by the infamous OOM killer. In case Linux is employed under circumstances where it would be less desirable to suddenly lose some randomly picked processes, and moreover the kernel version is sufficiently recent, one can switch off this overcommitting behavior using a command like:

# echo 2 > /proc/sys/vm/overcommit_memory

See also the kernel Documentation directory, files vm/overcommit-accounting and sysctl/vm.txt.

Dunbarton answered 10/9, 2010 at 11:54 Comment(0)
F
0

FreeBSD and Mac OS X have the reallocf() function that will free the passed pointer when the requested memory cannot be allocated (see man realloc).

Filterable answered 10/9, 2010 at 12:4 Comment(1)
Rather than using this, it would make a lot more sense to just write your own function to do so if you really want that behavior. But I can't imagine it being very useful - it's throwing away likely-valuable data.Nonappearance

© 2022 - 2024 — McMap. All rights reserved.