----------------------------------------------------------------------------------
@MSGID: 2:5055/182 2738ce0b
@PID: jNode ver. 1.5
@TID: jNode ver. 1.5
@CHRS: CP866 2
[](
https://telegra.ph/file/3c872fa66cd0e3a924c54.jpg)**Добби свободен**
Время воскресных очешуительных историй.
We need to go deeper с утечками памяти, бо разработчики, как
практика показывает, неважно себе представляют подкапотное поведение.
Итак, что происходит, когда область памяти по указателю void*
освобожается вызовом free()?
По факту, аллокатор (системный, кастомный или ОС) просто переносит
этот указатель в список свободных внутри себя (и отмечает это в своих
метаданных). Память не зануляется, указатель не разадресовывается и не обнуляется
автоматически. Таким образом, указатель не просто остается валидным. Он так и
продолжает смотреть на чанк, который уже возвращен в свободные, но, часто, все
еще содержит прежние данные. Это стандартное поведение. Зануление указателя
(чтобы попытка повторного обращения - грубая ошибка сама по себе - привела
к сегфолту) - это прерогатива программиста. Ни ОС, ни аллокатор не
делают этого автоматически - для скорости и потому, что существует calloc()
с memset() внутри.
Так вот. Если по какой-то причине программа занулит указатель раньше,
чем чанк будет помечен вызовом free() как свободный, он остается во
владении программы, но более недоступен - мы зачистили указатель. И освободить
его до конца работы программы мы уже не можем, это сделает лишь ОС,
прибирая мусор при том или ином завершении программы.
Именно это и называется утечкой памяти - это и ничто другое.
Заметим в скобках, что мы говорим об относительно простых типах.
Если по указателю содержится нетривиальный тип - что-то кроме, скажем,
массива указателей, которые смотрят на структуры, которыми владеет кто-то
другой - то необходим нетривиальный деструктор, последовательно, шаг за
шагом, освобождающий субструктуры и зануляющий их субординатные указатели.
Иначе утечка произойдет незаметно для программиста.
Ну и немного баден-бадена касательно инициализации. malloc() - и он
вызывается под капотом выражения new и оператора new - память не
инициализирует, как вы помните. __Выражение__ new, однако же, позволяет
инициализировать POD типы, а также некоторые типы STL (массивы, например) указанием
пустых скобок () или (см.стандарт C++) при вызове выражения new.
Надеюсь, стало немного понятнее про утечки. )))
http://fido.ortoped.org.ru/photo_2023-10-22_09-47-39.jpg
--- hssergey station
* Origin: jNode ver. 1.5 (2:5055/182)
SEEN-BY: 301/1 460/58 4500/1 5001/100 5005/49
5015/255 5019/40 5020/715 848
SEEN-BY: 5020/1042 4441 12000 5030/49 1081 5055/182
5058/104 5061/133
SEEN-BY: 5083/444
@PATH: 5055/182 5020/1042 4441