Handling of malloc() and realloc()

Asked

Viewed 7,494 times

7

I still don’t feel completely confident about using the malloc() or realloc(), these two ways are equivalent?

1)

int main()
{
    int x=0;
    char *s2,*s1;
    s1=NULL;
    s2=malloc(200);

    while(x++<3)
    {
        scanf(" %s", s2);
        s1=realloc(s1, strlen(s2));
        strcpy(s1, s2);
        printf("%s\n", s1);
    }

    free(s1);
    free(s2);
}

or making

2)

 while(x++<3)
    {
        scanf(" %s", s2);
        s1=malloc(strlen(s2));
        strcpy(s1, s2);
        printf("%s\n", s1);
        free(s1);
    }

What would happen in memory when we did the malloc twice, as well as so:

    int x=0;
    char *s2,*s1;
    s1=malloc(100); /*reservar aqui*/
    s2=malloc(200);

    while(x++<3)
    {
        scanf(" %s", s2);
        s1=malloc(strlen(s2)); /*e reservar aqui*/
        strcpy(s1, s2);
        printf("%s\n", s1);
        free(s1);
    }

Is there any way to reserve memory space like this? Only by allocating a space of 200 (as for example) and only then relocating exactly the necessary memory?

    scanf(" %s", s2);
    s2=malloc(strlen(s2));

What really makes a malloc() and realloc() internally in the memory?

  • But what was the point of whiles ? It’s just that I see strcpy when I suspect the intention was strcat, otherwise relocation in almost all cases would not be necessary. The goal is to read word by word and join in a string ?

  • It is just a small code to expose my doubt about memory allocation, just to understand the functioning of malloc() and realloc(), this code is only intended to be used to learn about memory allocation

2 answers

9


Definitions of malloc and realloc:

malloc:

This method allocates a space in the heap that has not been initialized, it returns a pointer to the allocated memory. The function’s signature is:

void *malloc(size_t size);

Where size_t corresponds to the integral data type returned by the operator sizeof and is used to represent the size (in bytes) of an object. It is defined (in the string header. h in the C language and the header in C++) as an unsigned integral type. It is just an indication that the type is used to contain the number of bytes of memory (and not the usual unsigned int).

The code below allocates memory to 10 integers and designates the address of the allocated memory (address of the first byte from memory) to the pointer of int ptr:

int * ptr = (int*) malloc(10 * sizeof(int));
  • If the system is not able to allocate the required space in the heap then the function will return null.

  • If the size is zero (malloc(0)), then the function can return both null as a valid pointer.

  • Of default the function returns a pointer of type void that needs to be properly casted before using( in the example above we use int* to do the casting).

  • The memory returned by the function is not initialized and contains values "garbage".

realloc:

This method changes the size of the memory block in the heap. Suppose a pointer ( say ptr) that is pointing a space in memory defined by a malloc, as we did in the explanation of malloc. And you want to increase the size to memory space pointed by ptr from 10 to 20, without losing the already allocated content in memory. In this case you can use the realloc. The signature of the function is:

void *realloc(void *ptr, size_t size);

Where ptr is the pointer to the allocated block, and size is the new size (in bytes) for the new memory block. It is possible that the function will move the memory block to another place if it is not able to allocate the space right after where it is already. In this case it will allocate a space of 20 integers elsewhere and copy the contents contained by the block of 10 integers in size. And so the value of ptr will change.

CARE TO BE TAKEN:

int * ptr1 = (int*) malloc(5 * sizeof(int));
int * ptr2 = ptr1;
ptr2 = (int*) realloc(ptr2, 10 * sizeof(int));

When realloc is called, the memory location pointed by both pointers can be offset (in case the contiguous space is not available right after the memory block). ptr2 will now point to the newly moved location in the heap (returned by realloc), but ptr1 is still pointing to the old site (which is now out of place).

PS:

To the realloc the first parameter to the function can be either a pointer to a memory block that your code was using or can be null pointer, in the latter case the function will behave as a malloc

  • 1

    I hope you have cleared your doubt with this explanation =)

  • 1

    Yes, that’s a very good answer, thank you very much. I’m going to leave a little time just to give some more exposure to this question and then validate an answer

6

The exact answer to this depends on the implementation detail of the memory management functions, but I would say that in most cases it does in the same. Some people just use realloc() using a null as the starting value.

The penultimate code will leak the first allocation of s1 because you don’t even have a reference to it after you’ve executed the core of the code, or that you wanted to, you can’t release the memory there. Of course, in a simple code like this, it doesn’t matter, it finishes the execution and nothing bad happens, but doing it in the middle of a huge code in production and if it is a pattern that repeats itself several times can create problems by dropping orphan allocations.

Note that in this specific example you do not need to keep allocating or relocating, you can use the same space as then the value is dropped. And even more, it would be better to make allocation in stack and have less headaches. I understand that it is just an isolated example, but it is good to know this so that it does not continue to reproduce it in real code as a good wrong practice.

In real code in production this is usually done differently. It is more common to allocate a reasonable size in stack and only after you have the actual text will you copy to heap making the necessary allocation already at the proper size. See What are and where are the "stack" and "heap"?.

Beware of strlen(), its use in some cases can cause more damage than the focus of the question.

And since the question even has a reward, let’s learn right that one should not do cast in the malloc() in almost every situation. It is less readable, redundant, hides certain types of errors among other problems, see Typecast malloc is recommended? and What is the difference in the syntax ptr = (int*) malloc (sizeof(int)) and ptr = malloc (sizeof(int))?.

Documentation of malloc() and realloc().

Is there any way to reserve memory space like this? Only by allocating a space of 200 (as for example) and only then relocating exactly the necessary memory?

I think this should answer: This prevents an array from being initialized with a variable size in C?.

What really makes a malloc() and realloc() internally in memory?

It depends on the compiler or even the library you are using, or the platform you are running on. Already knowing what the heap, understand that its allocation algorithms may vary as needed, and you can make your own way.

The most common is that this function is an abstraction that organizes the best way to work in each situation. In general it invokes the operating system to allocate a larger region of memory that may be 4KB, or normally multiples thereof, in some cases 2MB or 1GB, since these 3 are sizes of virtual memory pages commonly used in the operating system. And as it is being requested by the application it occupies these spaces. In a way it is very similar to the stack which has its entire memory allocated and waiting to be occupied by frames execution.

The problem becomes greater when it releases spaces and then it tries to reuse these spaces. There is an algorithm that tries to occupy these spaces in the best way possible, which is something complicated to reconcile everything. There occurs what we call memory fragmentation and the algorithm slows down to make allocations, unless the free() avoid this, which it will be much slower.

It would be nice to read more on How malloc organizes memory? and Variables are randomly allocated in memory?. Will also be useful How "free()" knows how much memory has to free? and What is page fault?.

The realloc() is a malloc() that changes the previously allocated size. A good algorithm tries to increase its size without changing its location, but it is not always possible, especially if it is increasing its size. And whether it is decreasing or changing the site object is common to increase memory fragmentation. The remaining site may still be reused, but it will not always be easy to put something of the proper size there. And when it changes its place, it can stay away from another object that it is always associated with, which decreases the location and messes up the memory cache. So abusing him can wreak havoc.

In the background both are only manipulators of a data structure that organizes the allocations. And if you have a specific need you can write a structure and algorithms that best suits your need.

Otherwise the question needs to be more specific about what you want.

  • If it is possible to try to explain more deeply how memory management works, or to cite some articles so I can read about this subject, I really want to learn not superficially. All the books I read don’t find a good article to really understand what’s going on in memory.

  • I can, but in a question about this, this one is more restricted. In fact, if you do research, I’ve answered a lot about it, a lot of it already has an answer, ask other specific things you don’t think. There’s a lot to talk about, I don’t have anything orgnanized.

Browser other questions tagged

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