How to free memory from an internal malloc to a function that returns a pointer?

Asked

Viewed 912 times

5

How to release a malloc internal to a function that returns a pointer? In a simple way to try to exemplify my doubt, consider the following function f:

int *f(int tam)
{
    int *ptr = malloc(tam * sizeof *ptr);

    return ptr;
}

Which uses dynamic memory allocation within the function and returns the allocated pointer. I am using, in a function (such as main) in the form:

int main(void)
{
    int tamanho = 5;

    int *ponteiro;

    ponteiro = f(tamanho);

    if(ponteiro != NULL)
    {
        free(ponteiro);
    }
    else
        puts("Memória insuficiente.");      

    return 0;
}

Where ponteiro receives the return of the function f(). Would be responsible for checking if there is memory available and give free() in the malloc() function as described above in main?

If so, in compound functions in call, would it also be done this way? The example below shows two functions: one calling the other,

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

int *f(int tam)
{
    int *ptr = malloc(tam * sizeof *ptr);

    return ptr;
}

int *g(int *ptr)
{
    return ptr;
}

int main(void)
{
    int tamanho = 5;

    int *ponteiro;

    ponteiro = g(f(tamanho));

    if(ponteiro != NULL)
    {
        free(ponteiro);
    }
    else
        puts("Memória insuficiente.");      

     return 0;
}

It would be the pointer that receives the "final" return responsible for the dynamic allocation of the malloc? And so indefinitely for such compound functions ?

2 answers

4


The basic rule is don’t do this. But if you do the path is the one you presented, there’s not much to invent. That is, if you will not follow an organization rule that everyone establishes as the clearest, then create your rule and take the risk.

The ideal is to always let the function responsible for allocating memory be responsible for releasing it, rarely do you have any advantage in doing different. Generally speaking, the philosophy of C functions that need an allocated memory that can exist beyond its duration is always to receive a pointer to memory previously allocated by another code. It is rare, and usually considered wrong, to allocate memory and return it for external use to the creative function.

The reason for this "rule" is precisely not to make it even more difficult to track the lifetime of an object. It is very easy not only to make mistakes but to create potentially dangerous situations. It may seem simple in an example contained like this, but in a real code it is very complicated to know if you should free the memory and if it has not yet been released.

Whoever allocates the memory should be responsible for all necessary treatment. If you don’t do this get ready to shoulder unnecessarily complicated management.

Following a few rules, managing dynamic memory in C is not that difficult. Of course, you can still forget what to do, you can make mistakes, get confused, but following a good organization you don’t get lost easily as some people imagine.

The example is very bad to demonstrate anything really useful but only to show the most correct way to do something similar:

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

int *f(int *ptr) {
    //faz alguma coisa com ptr aqui
    //do jeito que estava aqui, uma chamada do jeito errado criaria confusão
    //ainda não está ideal mas o exemplo todo não está
    return ptr;
}

void g(int *ptr) {
    //faz alguma coisa com ptr aqui
    return;
}

int main(void) {
    int tamanho = 5;
    //o importante é que o malloc agora está próximo do free, fica mais fácil acompanhar
    int *ponteiro = malloc(tamanho * sizeof *ponteiro); 

    g(f(ponteiro));

    if(ponteiro != NULL) { //só isto não garante nada em um exemplo mais completo
        free(ponteiro); //não é difícil associar este free ao malloc logo acima
    } else {
        puts("Memória insuficiente.");      
    }
}

I put in the Github for future reference.

Don’t take a solution and look for a problem to apply it. Find the best solution to a problem you have.

I only know three reasons to treat liberation elsewhere:

  1. artificially want to decrease a code in one place (doesn’t mean it’s a good thing);
  2. have a memory management function that assists the work (few people know how to do it right);
  3. is using something bad created by third parties and therefore you have no control to fix it.

In general C Apis require the consumer to be responsible for allocating memory, it is rare to deliver memory allocated by the API used.

Even if it seems right in a simple example it can be a bad idea in more complex examples.

C is a language where management should be done manually and needs a lot of care, if these precautions are not even so difficult. If you prefer more automatic management, choose C++ or a language with Garbage Collector.

  • Unfortunately it was necessary, because I had to return an array and the doubt arose.

  • If you had posted a real example, maybe I could show you how to do it differently. I only know three reasons to treat release elsewhere: 1) artificially wanting to decrease a code in one place (doesn’t mean it’s a good thing); 2) having a memory management function that helps the job (few people know how to do it right); 3) is using something created by third parties and therefore you have no control to fix it.

  • 1

    It could be so. What you did is correct within this wrong context :) What can I say goes up the use of free()? It is correct but depends on the exact context. In this example I know it works, but if you change some comma it might not be enough more. I can only say what is correct in real situation. If you want more automatic things look for another language like C++ or other more automatic yet.

  • Okay. I saw the answer redone, so I deleted the comment. I’ll start studying C++ too. Thanks for the answer. In fact I was in doubt only for the possibility of code to be executed like this, and if it could be better interpreted, but in the implementation I will keep your option.

  • Excellent response.

1

However, if the allocation you are going to make requires a little more performance and the function that is allocating the memory itself will be the same to de-locate, if that size is not __libc_use_alloca(size) (in the case of GCC), use the function alloca(); would fit the situation better since it gains in performance by not using heap and itself already displaces the allocated memory without the need to use the free(); avoiding the memory Leaking. If that’s not the case, and then, in that sense, performance is not a priority right now, consider using the calloc(); since it allocates and initializes the space allocated with zeros.

=-D

Browser other questions tagged

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