Handling malloc() and realloc()

I still don't feel completely confident about using malloc() or realloc(), are these two ways 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 doing

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 do malloc twice, like this:

    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 in this way? Just even allocating a space of 200 (like for example) and only then relocating exactly the necessary memory?

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

What does it really do a malloc() and realloc() internally in memory?

Author: Comunidade, 2018-08-14

2 answers

Definitions of malloc and realloc:

Malloc :

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

void *malloc(size_t size);

Where size_t corresponds to the integral data type returned by the sizeof operator 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 in the header in C ++) as a type full unsigned. 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 of the 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 heap then the function returns null.

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

  • From default the function returns a pointer of type void that needs to be properly cast before using( in the example above we useint* to do the casting ).

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

Realloc :

This method changes the size of the memory block in the heap. Suppose a pointer (say ptr) that is pointing to a space in memory defined by a malloc, like what we did in the explanation of malloc. And you want to increase the size of memory space pointed to by ptr from 10 to 20, without losing the content already allocated in memory. In this case you can use realloc. The function signature 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) to 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 content 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 deallocated (in case the contiguous space is not available right after the memory block). ptr2 will now point to the newly shifted location in heap (returned by realloc), but ptr1 is still pointing to the old location (which is now dislocated).

PS:

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

 5
Author: Um Programador, 2018-08-17 13:36:15

The exact answer to this depends on detail of implementation of the memory management functions, but I would say that in a good part of the cases it gives in the same. There are even those who only use realloc() using a NULL as the initial value.

The penultimate code will leak the first allocation of s1 because it doesn't even have a reference for it after it executes the core of the code, nor who wanted it can't release the memory there. Of course, in such simple code, little matters, ends execution and nothing bad it happens, but done in the middle of a huge code in production and if it is a pattern that repeats several times can create problems by dropping orphan allocations.

Note that in this specific example you do not need to be allocating or relocating, you can use the same space since then the value is discarded. And even more so, it would be better to do allocation in the stack and have less headache. I understand that it is only an isolated example, but it is good to know that so as not to continue reproducing it in real code as a misguided good practice.

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

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

And since the question even has a reward, let's learn for sure that one should not do cast in malloc() in almost all situations. It is less readable, redundant, hides certain types of errors among other problems, Vaja Typecast from malloc is recommended? and What is the difference in the syntaxes ptr = (int*) malloc(sizeof (int)) and ptr = malloc(sizeof (int))?.

Documentation of malloc() e realloc().

There any way to reserve memory space this way? Just even allocating a space of 200 (like for example) and only then relocating exactly the necessary memory?

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

What does a malloc() and realloc() actually do internally in memory?

Depends on the compiler or even library you are using, or the platform you are using rotate. Already knowing what the heap is, understand that the algorithms for allocating it can vary as needed, and you can make your own shape.

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 can be 4KB, or usually multiples of this, in some cases 2MB or 1GB, since these 3 are memory page sizes virtual commonly used in the operating system. And as it is requested by the application it will occupy these spaces. In a way it is very similar to the stack which has its entire memory allocated and waiting to be occupied by the execution frames.

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 possible way, which is somewhat complicated to reconcile everything. There what we call memory fragmentation occurs and the algorithm is slower to make allocations, unless free() prevents this, which will be much slower.

It would be nice to read more in how malloc organizes memory?Are and variables randomly allocated in memory?. It will also be useful how does "free ()" know how much memory it has to free? and what is page fault?.

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

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

Other than that the question needs to be more specific about what you want.

 4
Author: Maniero, 2020-07-30 16:14:16