free în C

Eliberează un bloc alocat cu malloc, calloc sau realloc, ca memoria să poată fi refolosită.

Sintaxă
#include <stdlib.h>
void free(void *ptr);

Ce face free

free întoarce sistemului memoria primită de la malloc, calloc sau realloc. După apel, blocul nu mai este al tău: pointerul păstrează aceeași adresă, dar folosirea lui este comportament nedefinit (pointer „atârnat”, dangling pointer).

Fiecare alocare trebuie eliberată exact o dată. free(NULL) este permis și nu face nimic, de aceea un obicei bun este să pui pointerul pe NULL imediat după free: o a doua eliberare devine inofensivă, iar o folosire greșită se vede mai ușor.

Pentru structuri care conțin pointeri spre alte blocuri, eliberează întâi blocurile interioare, apoi structura. Nu chema free pe adrese care nu vin de la alocare (variabile locale, literali, mijlocul unui bloc).

Parametri

Parametru Descriere
ptr Pointerul primit de la o funcție de alocare sau NULL.

Ce returnează

Nimic (void).

Exemple

Exemplul 1: Eliberare și punere pe NULL

După free, pointerul este pus pe NULL. Al doilea free primește NULL și nu face nimic.

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

int main(void) {
    double *preturi = malloc(3 * sizeof *preturi);
    if (preturi == NULL) return 0;
    preturi[0] = 4.5; preturi[1] = 12.0; preturi[2] = 7.25;
    printf("primul preț: %.2f lei\n", preturi[0]);
    free(preturi);
    preturi = NULL;
    free(preturi);   // free(NULL): fără efect
    printf("pointer: %s\n", preturi == NULL ? "NULL" : "adresă");
    return 0;
}

Rezultat

primul preț: 4.50 lei
pointer: NULL

Exemplul 2: Eliberarea unei structuri cu memorie interioară

Structura are un tablou alocat separat. Funcția de distrugere eliberează întâi tabloul, apoi structura.

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

typedef struct {
    size_t n;
    int *note;
} Catalog;

Catalog *catalog_nou(size_t n) {
    Catalog *c = malloc(sizeof *c);
    if (c == NULL) return NULL;
    c->note = calloc(n, sizeof *c->note);
    if (c->note == NULL) {
        free(c);
        return NULL;
    }
    c->n = n;
    return c;
}

void catalog_sterge(Catalog *c) {
    if (c == NULL) return;
    free(c->note);   // întâi memoria interioară
    free(c);         // apoi structura
}

int main(void) {
    Catalog *c = catalog_nou(25);
    if (c != NULL) {
        c->note[0] = 10;
        printf("catalog cu %zu locuri, prima notă %d\n", c->n, c->note[0]);
    }
    catalog_sterge(c);
    return 0;
}

Rezultat

catalog cu 25 locuri, prima notă 10

Exemplul 3: Folosire după free (nu rula așa)

Codul citește din blocul deja eliberat. Pe calculatorul de test a afișat 4, nu 500: memoria fusese deja refolosită. Poate afișa și vechea valoare sau se poate opri; cu -fsanitize=address, programul se oprește cu „heap-use-after-free”.

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

int main(void) {
    int *sold = malloc(sizeof *sold);
    if (sold == NULL) return 0;
    *sold = 500;
    free(sold);
    printf("%d\n", *sold);   // GREȘIT: blocul nu mai este al nostru
    return 0;
}

Rezultat posibil (comportament nedefinit)

4

Greșeli frecvente

  • Eliberezi de două ori același bloc (double free). Este comportament nedefinit și poate strica administrarea memoriei. Pune pointerul pe NULL după free.
  • Folosești memoria după free. Programul poate părea că merge, apoi dă rezultate greșite mai târziu; compilează cu -fsanitize=address în timpul dezvoltării ca să prinzi astfel de erori.
  • Chemi free pe o variabilă locală, pe un literal sau pe p + 1. Doar adresele exacte returnate de funcțiile de alocare pot fi eliberate.
  • Eliberezi structura înaintea memoriei interioare. După free(c), c->note nu mai poate fi citit, așa că tabloul rămâne alocat pentru totdeauna.

Comenzi înrudite

  • malloc: Cere sistemului un bloc de memorie de mărimea dată, în timpul rulării, și returnează adresa lui sau NULL dacă nu reușește.
  • calloc: Alocă memorie pentru un tablou de count elemente a câte size octeți și pune zero în toți octeții.
  • realloc: Schimbă dimensiunea unui bloc alocat dinamic, păstrând conținutul; poate muta blocul la altă adresă.
  • Comportament nedefinit (undefined behavior): Situațiile pentru care standardul C nu spune ce se întâmplă: programul poate merge, poate da rezultate greșite sau se poate opri.
  • Pointeri (& și *): O variabilă care păstrează adresa altei variabile; cu * citești sau modifici valoarea de la acea adresă.
Comunitate & Schimb de cunoștințe

Întrebări & Exemple de Cod: free

Ai o nelămurire despre utilizarea comenzii free sau ai descoperit un truc / fragment de cod util? Distribuie-l cu ceilalți programatori!

💬

Fii primul care pune o întrebare sau distribuie un fragment de cod / prompt!

Nu au fost adăugate încă întrebări sau exemple de cod pentru această pagină. Dacă ai întâlnit o problemă sau ai un snippet util, adaugă-l mai jos pentru a-i ajuta pe ceilalți.

Comunitate Adaugă o întrebare sau distribuie un cod

Moderare & Siguranță:

Pentru a menține calitatea și securitatea informațiilor, fiecare întrebare sau fragment de cod/prompt este analizat (manual sau prin moderare asistată de AI) înainte de publicare.