To mnie martwiło od wieków.
Wszyscy uczymy się w szkole (przynajmniej ja byłem), że MUSISZ uwolnić każdy przydzielony wskaźnik. Jestem jednak trochę ciekawy, jakie są rzeczywiste koszty nie zwalniania pamięci. W niektórych oczywistych przypadkach, takich jak malloc
wywołanie w pętli lub części wykonania wątku, bardzo ważne jest zwolnienie, aby nie było wycieków pamięci. Ale rozważ następujące dwa przykłady:
Po pierwsze, jeśli mam kod, to coś takiego:
int main()
{
char *a = malloc(1024);
/* Do some arbitrary stuff with 'a' (no alloc functions) */
return 0;
}
Jaki jest tutaj prawdziwy wynik? free
Uważam, że proces umiera, a następnie przestrzeń stosu i tak nie ma miejsca, więc nie ma żadnych szkód w nieodebraniu wezwania do (jednak zdaję sobie sprawę z tego, jak ważne jest, aby mieć to do zamknięcia, konserwacji i dobrej praktyki). Czy mam rację w tym myśleniu?
Po drugie, powiedzmy, że mam program, który działa trochę jak powłoka. Użytkownicy mogą deklarować zmienne podobne, aaa = 123
a te są przechowywane w jakiejś dynamicznej strukturze danych do późniejszego wykorzystania. Najwyraźniej wydaje się oczywiste, że użyłbyś jakiegoś rozwiązania, które wywoła jakąś * funkcję przydzielania (skrót, lista połączona, coś podobnego). W przypadku tego rodzaju programu nie ma sensu nigdy zwalniać po wywołaniu, malloc
ponieważ zmienne te muszą być obecne przez cały czas podczas wykonywania programu i nie ma dobrego sposobu (jak widzę) na wdrożenie tego przy użyciu statycznie przydzielonego miejsca. Czy źle jest mieć część pamięci, która jest przydzielana, ale zwalniana tylko jako część procesu kończącego się? Jeśli tak, jaka jest alternatywa?
free(a)
tak naprawdę nic nie robi, aby zwolnić pamięć! Po prostu resetuje niektóre wskaźniki w implementacji liboc malloc, które śledzą dostępne fragmenty pamięci na dużej stronie pamięci zmapowanej (zwykle nazywanej „stertą”). Ta strona będzie nadal zwalniana dopiero po zakończeniu programu, a nie wcześniej.