Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

179
Visualizações
Freeing all allocated memory in case of failure

I'm working on a C project (assignment for school). One of the demands is that in case of malloc() failure, the program must free() all allocated memory and exit().

Consider a case where function A() constructs a linked-list and in each iteration it calls to another function, B(). Now, if a malloc failure occured at B(), it must free() the memory it allocated but function A() should do that as well.

Things are getting quite complicated when you have a tree of function calls larger than two.

In my previous project I used a flag to notify a malloc() failure - if a function uses another function which may use malloc(), it has to check the flag right after. It worked, but code got kinda messy.

Is there a neat solution for this problem?
Of course, with "real" applications all memory is de-allocated by the OS, but I guess this demand is pedagogical..

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

I think the easiest approach is to create a custom allocator (as somebody already noted in a deleted post) to keep track of all your allocations, then do a custom deallocator, use these for all your heap memory needs.

if a malloc fails you have the list of previously allocated blocks at easy reach.

e.g. (you need to redo this cause it is not effective and should be optimized but shows the principle and only ocular compilation)

typedef struct
{
  void* pMemory; /* for the allocated memory */
  size_t size;   /* for better debugging */

} MemoryBlock;

#define MAXBLOCKS 1000

MemoryBlock myheap[MAXBLOCKS]; // global so zero:ed
static int block = 0;

void* myalloc(size_t size)
{
   static int block = 0;

   // you should check vs MAXBLOCKS 

   myheap[block].pMemory = malloc(size); 
   myheap[block].size = size;   

   // check if it failed.
   if ( myheap[block].pMemory == NULL )
   {
      for (int i = 0; i < block; ++i)
      {
         myfree(myheap[i].pMemory);
      }
      fprintf( stderr, "out of memory\n");
      exit(EXIT_FAILURE);
   }
   else
   {
     return myheap[block++].pMemory;
   }
}

void myfree(void* p)
{
   for (int i = 0; i < block; ++i)
   {
      if ( p == myheap[i].pMemory )
      {
         free(myheap[i].pMemory);
         myheap[i].pMemory = NULL;
         return; 
      }
   }
}
over 4 years ago · Santiago Trujillo Relatório

0

Yes. The best (and conventional) way is to initialize every pointer value to zero. Then set it during the malloc() assignment. Ex: myPtr = malloc( 10 );

It will be zero in case of failure, and you check that. And finally, when you go about freeing, you always check the pointer value before calling free():

if ( myPtr != 0 )
    free( myPtr );

There is no need for an extra flag.

over 4 years ago · Santiago Trujillo Relatório

0

You could look into the atexit() function, to register code that will be executed when the program terminates. Such code can then check if there is anything that needs to be free()d.

Note that atexit() has no way to unregister. So you need to make sure that you register each cleanup function only once, and that it does the right thing when there is nothing to clean up.

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

int *ptr1;
char *ptr2;
int clean1_registered, clean2_registered;

void clean1(void)
{
    printf("clean1 called\n");
    if (ptr1) {
        free(ptr1);
        ptr1 = NULL;
    }
}

void clean2(void)
{
    printf("clean2 called\n");
    if (ptr2) {
        free(ptr2);
        ptr2 = NULL;
    }
}

void B(void)
{
    ptr2 = malloc(100);
    if (!clean2_registered) {
        atexit(clean2);
    }
}

void A(void)
{
    ptr1 = malloc(100 * sizeof(int));
    if (!clean1_registered) {
        atexit(clean1);
    }
    B();
}

int main(int argc, char **argv)
{
    A();
}
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda