Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

realloc but only first few bytes is meaningful

Assume I have used ptr = malloc(old_size); to allocate a memory block with old_size bytes. Only the first header_size bytes is meaningful. I'm going to increase the size to new_size.

new_size is greater than old_size and old_size is greater than header_size.

before:

/- - - - - - - old_size - - - - - - - \
+===============+---------------------+
 \-header_size-/

after:

/- - - - - - - - - - - - - - - new_size - - - - - - - - - - - - - - - - - - -\
+===============+------------------------------------------------------------+
\- header_size-/

I don't care what is stored after ptr + header_size because I'll read some data to there.

method 1: go straight to new_size

ptr = realloc(ptr, new_size);

method 2: shrink to header_size and grow to new_size

ptr = realloc(ptr, header_size);
ptr = realloc(ptr, new_size);

method 3: allocate a new memory block and copy the first header_size bytes

void *newptr = malloc(new_size);
memcpy(newptr, ptr, header_size);
free(ptr);
ptr = newptr;

Which is faster?

like image 766
lqs Avatar asked Nov 06 '12 08:11

lqs


1 Answers

Neither malloc (for the whole block) nor realloc (for the space beyond the size of the old block when increasing the size) guarantee what the memory you receive will contain so, if you want those excess bytes set to zero (for example), you'll have to do it yourself with something like:

// ptr contains current block.
void *saveptr = ptr;
ptr = realloc (ptr, new_size);
if (ptr == NULL) {
    // do something intelligent like recover saveptr and exit.
}
memset (ptr + header_size, 0, new_size - header_size);

However, since you've stated that you don't care about the content beyond the header, the fastest is almost certainly a single realloc since that's likely to be optimised under the covers.

Calling it twice for contraction and expansion, or calling malloc-new/memcpy/free-old is very unlikely to be as efficient though, as with all optimisations, you should measure, don't guess!

Keep in mind that realloc doesn't necessarily have to copy your memory at all. If the expansion can be done in place, then an intelligent heap manager will just increase the size of the block without copying anything, such as:

+-----------+   ^        +-----------+ <- At same address,
| Old block |   | Need   | New block |      no copying
|           |   | this   |           |      involved.
+-----------+   | much   |           |
| Free      |   | now.   |           |
|           |   v        +-----------+
|           |            | Free      |
|           |            |           |
+-----------+            +-----------+
like image 53
paxdiablo Avatar answered Nov 15 '22 08:11

paxdiablo