Free

ceer
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.

```c #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;
}


<dfn>Funkcja <b>free()</b> może zmienić zawartość zwalnianego bloku pamięci, ale nie zmienia wskaźnika.
Po wywołaniu <b>free()</b> 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 <b>free()</b> wskazywał na pewien obszar pamięci, wartość [[C/NULL]]:
```c
  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.</dfn>

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 [[C/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ż:

0 komentarzy