What happens to memory when "realloc()" reallocates a memory block to a value less than the original?

Asked

Viewed 158 times

10

Suppose I allot a dynamic matrix of 10 ints and assign some values values to it, then I use the function realloc() to reallocate the matrix to 3 ints, what happens to the other 7 ints, they will be released from memory by the function realloc() or the memory will leak?

Another question: In this specific case it makes sense to assign the return of realloc() for a temporary variable, after all I am not ordering new memory, but rather decreasing the memory I had already allocated.

Here is an example:

#include <stdio.h>
#include <stdlib.h>

int main() {
  int *values = malloc(10 * sizeof(int));

  for(int i = 0; i < 10; ++i) {
    values[i] = i;
  }

  int *tempValues = realloc(values, 3 * sizeof(int));

  if(tempValues != NULL) {
    values = tempValues;
  }

  free(values);

  return 0;
}

2 answers

7


what happens to the other 7 ints, they will be released from memory by the function realloc() or the memory will leak?

It will be released. Technically the memory will not leak, but nothing guarantees that the release will provoke the reuse of this space. So even if there isn’t a leak there can be a waste of that memory, so it’s rare for someone to make a, realloc() decreasing the size, since this is only useful for large portions, and also because it is common to need to increase the number of items soon after reducing.

In higher-level languages, you usually have structures that handle this well abstractly and do what’s best without the programmer having to interfere (you can do it optionally), in C the common is someone using some library that gives it or that one creates a structure that better handles that form. Doing this or even moving manually is common to have a strategy to reuse the items and the realloc() is less applied loose in application code than you might imagine. Incredible as it seems it’s usually best to waste a little space. It is only worth decreasing if you are sure that you will not need to grow again and the gain is expressive and necessary.

The realloc() is mostly used to grow the object, because in general there will actually be a relocation. Decreasing the size of the object will not cause a relocation.

Memory fragmentation

One of the ways this happens is precisely to release a portion of memory (realloc() is only one of the techniques) and it is unused because other objects can be larger than this liberated space. That’s bad, but it’s not tragic, and it’s more common than you think. In fact, unless you’re on a device with very scarce memory, it doesn’t pay to try to save that memory (for everything has an exception). The example quoted probably does not compensate, you save a few bytes and that may never be used again. But it can be used and be worse.

There’s another kind of fragmentation that is the fact that objects that are used together are in different places. If an object fits in this released space but another related space does not fit it will be placed in another point of memory, far from this, when accessing and the objects are separated will have two accesses and will probably be out of cache. Fragmentation worsens the reference location. When objects are together it is likely to be accessed more efficiently, when they are related.

You trade a little memory for performance.

In this specific case it makes sense to assign the return of realloc() for a temporary variable

It makes sense in this restricted case. If it was another case I don’t know, it depends on context. Let’s say this was a function that does something more realistic and receives a pointer to an object and reduces its size. You couldn’t use the free(), right?

If it is certain that you are reducing the size there can be no failure. Nothing in the specification says that it cannot fail, but we know that it does not fail, because if it was not so it would probably almost never relocate to reduce the size, because the cost would be too high. If you’re doing it in C, you’re usually looking for performance. In normal implementations you can count that there will be no failure and no need to assign anything extra or test if the reduction worked (in theory the code will not be 100% portable, but in practice it is, it would be the same as the staff says that stack and heap are implementation details, but in practice everyone develops thinking that they exist and have universally known semantics). Some guards can be interesting if you use this undocumented behavior and know that the code can run on any compiler, even the most "crazy".

Just be careful not to use the original variable after giving the realloc() and before reassigning it, as you did correctly, so if you use temporary variable always use this pattern to reassign right after the test.

Completion

If you want to know more read the documentation. It’s not official, but it’s like it is, it’s where there’s curated good C/C professionals++.

The example is not good to show how things happen in the real world. It serves to show the mechanism, just have clear this difference not to reproduce the same behavior in real code.

4

I don’t know if I’ll be able to answer your question, but come on..

What happens to memory when realloc realoca a block of memory for a value less than the original?

Simply the realloc() will make a free() what has been reduced, marking so that the memory released is available for other uses.

It makes sense to assign realloc return to a variable temporary, after all I am not requesting new memory, but yes diminishing the memory I had already allocated.

Checking the definition of realloc, the realloc() has as return: "A Pointer to the reallocated memory block, which may be either the same as ptr or a new Location."

And why you should use the temporary variable to check?

If you look at the reference I passed above, you will also see the following statement:

"A null-Pointer indicates that the Function failed to allocate Storage, and Thus the block pointed by ptr was not modified."

In other words if the realloc() fail you can still use the original block, through its variable *values, unlike what might happen if you did not use the temporary variable, and set the realloc() straight to her, and the same failed, returning a NULL and so you mess up the whole program.

In my view there is no problem in creating the temporary variable, you should!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.