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ż: