как «свободно» работает при увеличении указателя - PullRequest
21 голосов
/ 11 марта 2010

Когда вызывается malloc, размер сохраняется рядом с выделенным блоком, так что free будет знать, сколько освободить и т. Д. (http://c -faq.com / malloc / freesize.html ).

Мой вопрос: скажем, у нас есть динамически распределенная память, а затем в коде мы увеличиваем указатель

 pointer++

А потом, если я позвоню

free(pointer) 

какая память на самом деле освобождается.

Количество выделенных байтов, начиная с текущего адреса, на который указывает указатель, или с базового адреса, которому он был назначен.

Ответы [ 9 ]

28 голосов
/ 11 марта 2010

Вам нужно free() тот же указатель, который вы получили от malloc(). Увеличение, изменение или изменение - это неопределенное поведение, которое обычно является ошибкой сегментации.

Думайте о указателе, который вы получаете как книгу из библиотеки. Вы возвращаетесь домой и читаете это. После этого вы убираете титульную страницу и заднюю часть книги и возвращаете ее библиотекарю. Примет ли он это или у вас сейчас серьезные проблемы? ;-)

10 голосов
/ 11 марта 2010

Вы можете позвонить free() только на значение, которое вы ранее получили от malloc(), calloc() или realloc() (или NULL). Все остальное не определено.

Например, реализация может хранить размер выделенного блока в 4 байта до адреса возврата из malloc(). Затем free() возвращается на 4 байта и определяет размер. Это не сработает, если вы не передадите исходный указатель обратно на free().

6 голосов
/ 11 марта 2010

Это приведет к неопределенному поведению. Скорее всего, это приведет к краху вашей программы сразу или позже.

4 голосов
/ 11 марта 2010

Если вы увеличиваете указатель без сохранения исходного неправильного местоположения, вы не можете вызывать его бесплатно. Вы должны сохранить исходное местоположение где-нибудь и использовать временную точку при увеличении.

4 голосов
/ 11 марта 2010

Это неопределенное поведение. И это, скорее всего, приведет к проблемам позже.

3 голосов
/ 11 марта 2010

Код, управляющий свободным хранилищем, предполагает, что вы не передадите ему неправильный указатель. Он берет все, что вы даете, не проверяет его правдоподобность и интерпретирует его так же, как интерпретирует правильный указатель. Он будет действовать в соответствии с любыми значениями, которые он читает из любых областей памяти, на которые он смотрит, при условии, что указатель был правильно получен. Если вы вручили ему случайный указатель, он найдет бессмысленные значения и, следовательно, будет действовать бессмысленно.

Это называется неопределенное поведение , и это подло. Это может привести к форматированию вашего жесткого диска, загрузке процессора или, по-видимому, к тому, что ваша программа будет работать так, как ожидается до выхода на пенсию. Никогда не знаешь.

3 голосов
/ 11 марта 2010

выполнение pointer++ исходного указателя ужасно неправильно. результат освобождения может отличаться в разных реализациях, но вам определенно не следует делать это.

2 голосов
/ 11 марта 2010

Это то, что мы называем ошибкой утечки памяти / сегментации.

Вы ДОЛЖНЫ передать в free () то же значение указателя, что и значение, полученное от malloc (), иначе ваше приложение будет плохо себя вести / зависать.

0 голосов
/ 11 марта 2010

Указатель, возвращаемый функцией malloc (), указывает непосредственно на память в куче, которая будет использоваться вашей программой.

Однако это не единственная выделенная память. Несколько байтов выделяются в ячейках памяти, непосредственно предшествующих возвращенному указателю, которые указывают размер куска в куче. Это не используется вашей программой, но обязательно понадобится бесплатно.

Когда вызывается free (p), информация о его порции в куче содержится, скажем, в местах от p-4 до p-1. Конечно, это зависит от реализации, но детали не должны касаться программиста. Единственное, что нужно знать программисту, это то, что free использует эту область памяти , чтобы освободить часть памяти из кучи, и эта область получается из исходного указателя p.

Другими словами, если вы вызываете free на p, это будет иметь смысл только в том случае, если malloc однажды вернул точно p.

Если вы передадите указатель, который не был создан с помощью malloc, кто знает, что будет лежать в p-1, p-2 и т. Д.? Это, вероятно, приведет к катастрофической неудаче.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...