OK, istnieje uzasadniona dużo zamieszania wyjaśniając dokładnie, co zamówić niezbędne free()
połączenia muszą być, więc będę spróbuj wyjaśnić, co ludzie próbują uzyskać i dlaczego.
Zaczynając od podstaw, aby zwolnić pamięć, która została przypisana użyciu malloc()
, wystarczy zadzwonić free()
z dokładnie wskaźnika które zostały podane przez malloc()
.Więc na ten kod:
int **a = malloc(m * sizeof(int *));
trzeba dopasowanie:
free(a);
i dla tej linii:
a[i]=malloc(n * sizeof(int));
trzeba dopasowanie:
free(a[i]);
Wewnątrz podobna pętla.
Tam, gdzie komplikuje się to kolejność, w której to musi się stać. Jeśli kilka razy dzwonisz do malloc()
, aby uzyskać kilka różnych porcji pamięci , to w ogóle nie ma znaczenia, którą z nich wywołujesz free()
, kiedy wykonałeś z nimi zlecenie. Jednak kolejność jest bardzo ważna z uwagi na konkretny powód: używasz jednego fragmentu z malloc
ed pamięci do przechowywania wskazówek do innych części przechowywanych w pamięci malloc
. Ponieważ koniecznością nie próba odczytu lub zapisu pamięci kiedy już oddał z free()
, oznacza to, że będą musieli uwolnić kawałki z ich wskaźników zapisanych w a[i]
przed Ci uwolnić a
sam porcja. Poszczególne porcje ze wskazówkami zapisanymi w a[i]
nie są zależne od każdego innego , więc mogą być free
dw dowolnej kolejności.
więc oddanie to wszystko razem, otrzymujemy w ten sposób:
for (i = 0; i < m; i++) {
free(a[i]);
}
free(a);
ostatnia wskazówka: podczas wywoływania malloc()
, rozważyć zmianę tych:
int **a = malloc(m * sizeof(int *));
a[i]=malloc(n * sizeof(int));
do:
int **a = malloc(m * sizeof(*a));
a[i]=malloc(n * sizeof(*(a[i])));
Co to robi? Kompilator wie, że a
jest int **
, więc może oznaczać, że sizeof(*a)
jest taki sam jak sizeof(int *)
. Jednakże, jeśli później zmienisz zdanie i chcą char
s lub short
s lub long
s lub cokolwiek w swojej tablicy zamiast int
S lub dostosować kod do późniejszego stosowania w coś innego, trzeba będzie zmienić tylko ten pozostały odniesienie do int
w pierwszej cytowanej linii powyżej, a wszystko inne automatycznie znajdzie się dla ciebie. Spowoduje to usunięcie niezauważonych błędów w przyszłości.
Powodzenia!
Konflikt terminologiczny: to nie jest to, co C zwykle nazywa "tablicą wielowymiarową". Jest to jedyny sposób na użycie składni "a [i] [j]", jednocześnie pozwalając, aby oba wymiary były nieznane w czasie kompilacji. Innym rodzajem tablic wielowymiarowych jest tablica tablic, zamiast tej tablicy wskaźników do (pierwszych elementów) tablic. –