Biblioteka standardowa » Stdlib.h

Free

  • 2010-10-31 18:27
  • 0 komentarzy
  • 2796 odsłon
  • Oceń ten tekst jako pierwszy
void free(void *p);

Funkcja dealokuje (zwalnia) obszar pamięci wskazany przez wskaźnik p, o ile jest on różny od NULL. W przeciwnym wypadku nie robi nic. Argument p musi być wskaźnikiem do obszaru uprzednio przydzielonego przez jedną z funkcji: malloc, calloc lub realloc.

Ponieważ język C pozbawiony jest tzw. "odśmiecacza", dlatego każdemu wywołaniu jednej ze wspomnianych funkcji alokujących pamięć musi odpowiadać wywołanie free(). W przeciwnym wypadku nastąpi tzw. Wyciek_pamięci.

Przykład 1.


#include <stdio.h>
#include <stdlib.h>
 
int main ()
{
  int *p; /* wskaźnik na zmienną typu całkowitego */
  /* alokacja miejsca pod 10-elementową tablicę elementów typu int */
  p = malloc( 10 * sizeof(int) );
  if( p == NULL )
  {
    /* obsługa błędu, jeśli alokacja się nie powiodła */
  }
 
  free(p);  /* zwolnienie obszaru pamięci wskazywanej przez p */
 
  return 0;
}


Funkcja free() może zmienić zawartość zwalnianego bloku pamięci, ale nie zmienia wskaźnika.
Po wywołaniu free() zazwyczaj można robić ze zwolnionym blokiem pamięci wszystko to, co przed jego zwolnieniem. Warto zabezpieczyć się przed taką ewentualnością, przypisując wskaźnikowi, który przed wywołaniem funkcji free() wskazywał na pewien obszar pamięci, wartość NULL:
  free(p);
  p = NULL;

Ponadto należy pamiętać, by nie wywoływać funcki free() wielokrotnie na tym samym wskaźniku, bo niesie to za sobą nieokreślone konsekwencje.


Przykład nr 2 - dynamiczna alokacja tablicy dwuwymiarowej.


   W poniższym przykładzie dynamicznie alokowana jest dwuwymiarowa tablica. Warto zauważyć, że najpierw alokowana jest tablica wskaźników, a następnie, w pętli, każdemu jej elementowi przypisywana jest tablica elementów typu double.
   Zwalnianie zajętej pamięci musi jednak odbywać się w odwrotnej kolejności: najpierw w pętli zwalniana jest każda z tablic elementów typu double, a dopiero później tablica wskaźników. Warto zauważyć, że gdyby najpierw została zwolniona tablica wskaźników, nie można byłoby uzyskać dostępu do żadnej z tablic elementów typu double, a tym samym zwolnić pamięci przez nie zajętej, co skutkowałoby wspomnianym wyciekiem pamięci.

#include <stdio.h>
#include <stdlib.h>
 
int main ()
{
  int i;
  const int wiersze = 6, kolumny = 5;
   double **p;
 
  /* alokacja miejsca pod tablicę wskaźników */
  p = malloc ( wiersze * sizeof (double *) );
  if(!p) abort();
 
  for (i = 0; i < wiersze; i++) {
      /* alokacja miejsca pod tablice elementów typu double */
    p[i] = malloc ( kolumny * sizeof (double) );
    if(!p[i]) abort();
  }
 
  /* użycie p */
  p[0][0] = 15;
  p[4][3] = 28;
 
  /* zwolnienie zajmowanego obszaru pamięci */
  for (i = 0; i < wiersze; i++) {
    free (p[i]);
  }
  free (p);
 
  return 0;
}


Poniższy przykład ma pokazać, że bardziej skomplikowane deklaracje, jak np. alokowanie pamięci pod wskaźnik na wskaźnik, albo pod wskaźnik na strukturę, w której znajdują się wskaźniki, zazwyczaj wiąże się ze zwalnianiem poszczególnych elementów w odwrotnej kolejności, niż zostały one zaalokowane.

Zobacz też: