Страницы

Поиск по вопросам

вторник, 28 января 2020 г.

Откуда функция free знает, сколько конкретно байтов памяти освобождать [дубликат]

#c #память #выделение_памяти


        
             
                
                    
                        
                            На этот вопрос уже даны ответы здесь:
                            
                        
                    
                
                        
                            Откуда C/C++ знает сколько надо освободить памяти, если
не знает размер массива?
                                
                                    (2 ответа)
                                
                        
                                Закрыт 1 год назад.
            
                    
Я новичок в программировании на языке Си. Вопрос по поводу работы функции free стандартной
библиотеки stdlib.h. Допустим, я выделил память для 100 символов:

char *pointer = malloc(100 * sizeof(char));


А как грамотно освободить эту память? Необходимо освобождать каждый char

for (int i = 0; i < 100; i++) free(pointer[i]);


или достаточно

free(pointer);


одним вызовом функции free? Я склоняюсь ко второму варианту, поскольку значение pointer[i]
из первого варианта не является указателем. Но откуда функция free знает, сколько памяти
я выделил через malloc? Это где-то записано в оперативной памяти или здесь используется
какая-то хитрость?
    


Ответы

Ответ 1



free(pointer); вполне достаточно. Диспетчер памяти сам разберется, сколько памяти освободить. Он хранит эту информацию где-то в своих внутренних структурах. Как именно - зависит от конкретной реализации. Например, как вариант - вы запрашиваете malloc, при этом выделяется памяти чуть больше - ну, на какие-то, скажем, 4-8 байт, и вам возвращается указатель, смещенный на эти 4-8 байт, в которые менеджер записывает длину (и не только - если памяти выделить побольше:)). А при освобождении - он отсчитывает от переданного указателя нужное число байт и читает сохраненную информацию. Еще раз - написанное не означает, что все сделано именно так, это всего лишь один из возможных вариантов. Как именно выделять память и где хранить служебную информацию - стандарт не определяет. Если вы хотите писать переносимые программы - вас это интересовать (для применения в своем коде) не должно...

Ответ 2



malloc поддерживает внутренную структуру, в которой хранит кроме прочего и размеры всех выделенных кусков памяти. В glibc есть интерфейс для доступа к этой информации: size_t malloc_usable_size(void*). Ну и вообще там много интересного: https://www.gnu.org/software/libc/manual/html_node/Summary-of-Malloc.html#Summary-of-Malloc

Ответ 3



Процесс освобождения памяти должно "зеркально" соответствовать процессу его выделения. В данном случае вы выделяли память одним вызовом malloc. Значит освобождать вы ее будете одним вызовом free. Ни о каком "освобождать каждый char" не может быть и речи. В традиционной реализации, malloc выделит больше памяти, чем вы запросили. В дополнительные байты памяти (обычно в начале выделенного блока) будет записан размер выделенного блока памяти +-----+-------------------------- ----+ | 100 | ... | +-----+-------------------------- ----+ ^ ^ ^ | | адрес, который `malloc` вернет вам в качестве результата | | | размер блока, записанный туда `malloc` | начало фактически выделенного `malloc` блока Когда вы вызовете free(pointer), функция free просто прочтает размер блока из области памяти "слева" от адреса pointer - так она узнает, сколько памяти нужно освободить. Вот и вся "хитрость". Записанный размер может быть полным размером блока или полезным размером блока, а также может меняться в большую сторону из соображений выравнивания размеров блоков. Это все детали реализации, как, впрочем, и весь механизм.

Комментариев нет:

Отправить комментарий