c вопросы о malloc (повреждение памяти)

Если при использовании malloc создается дамп ядра с ошибкой:

malloc(): memory corruption: ....... ***

Означает ли это, что malloc пытался выделить несвободную память? ЕСЛИ так, каковы причины этого?


person user105033    schedule 28.10.2009    source источник
comment
Может быть результатом UB, вызванного в строке где-то перед вашим вызовом malloc.   -  person dirkgently    schedule 28.10.2009


Ответы (5)


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

Многие реализации malloc хранят часть своих данных в памяти, другими словами:

+--------------------------------+
|14 bytes -> Padding             | 
+--------------------------------+
|2 bytes -> Internal malloc info |
+--------------------------------+
|6 bytes -> Your data            |
+--------------------------------+
|8 bytes -> Padding              |
+--------------------------------+
|2 bytes -> Internal malloc info |
+--------------------------------+

Поэтому, если какой-то ваш код или библиотека запишет 16 байтов в этот 6-байтовый буфер, он перезапишет заполнение и 2 байта внутренней информации о malloc. В следующий раз, когда вы вызовете malloc, он попытается пройтись по своим данным, чтобы найти место, наткнется на перезаписанное пространство, и это будет бессмысленно, поскольку вы перезаписали его, повредив кучу.

В зависимости от реализации такая ошибка также может быть вызвана двойным освобождением.

person Louis Gerbarg    schedule 28.10.2009
comment
ПРИМЕЧАНИЕ: это не требует, чтобы вы переписали память, которую вы ранее получили от malloc, как таковую - просто что-то где-то перезаписало структуры памяти, которые malloc пытается использовать в точка, где вы это называете. У вас может быть переполнение буфера в любой части вашего кода (или включенной библиотеки), так как я знаю, что нет требования, чтобы malloc извлекал свою память из отдельного пула, чем новый. Они вполне могут использовать одну и ту же кучу. И даже если их нет, по опр. ваше приложение должно иметь доступ к памяти, обрабатываемой malloc, и любая случайная запись ptr может повредить внутренности malloc - person Mordachai; 28.10.2009
comment
Старая привычка из-за того, что вы работали над ОС и потратили много времени на работу с ее реализацией malloc, в этом посте вы имеете в виду все, что выше кода библиотеки C. По общему признанию, в библиотеке c также есть код с ошибками malloc, поэтому ваша точка зрения остается в силе даже в этом случае. - person Louis Gerbarg; 28.10.2009

Скорее всего, это не проблема самого malloc. Скорее, это проблема, связанная с тем, что ваше приложение изменяет части кучи, которые не должны.

Если вы работаете в Linux, попробуйте использовать Valgrind, чтобы увидеть, какой код уничтожает вашу кучу.

person R Samuel Klatchko    schedule 28.10.2009
comment
+1 за предложение Valgrind. Эта программа может определить наиболее распространенные проблемы, связанные с памятью, в вашей программе. - person Denilson Sá Maia; 29.05.2010

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

Иногда это может быть вызвано освобождением указателя, который не был выделен функцией malloc() и др., или повторным освобождением (двойным освобождением) указателя, выделенного функцией malloc(). Например, освобождение статического буфера — плохая идея; вы получите коррупцию.

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

person Jonathan Leffler    schedule 28.10.2009

Есть несколько вещей, которые являются обычными причинами повреждения кучи:

  • превышение выделения памяти (запись после конца выделенного блока)
  • двойное освобождение блока
  • использование указателя после его освобождения
  • и, конечно же, что-то, ошибочно записывающее через указатель, который не имеет ничего общего с предыдущим выделением («удар тарана» или мошеннический указатель) — это общий случай, который включает в себя все вышеперечисленное.

Эти проблемы бывает трудно отладить, потому что причина и следствие часто разделены во времени и пространстве (разные области кода). Таким образом, ошибка не будет замечена до тех пор, пока не пройдет вечность (в компьютерном времени) после выполнения ошибки, вызвавшей проблему.

Использование отладочной кучи может быть очень полезным при отладке этих проблем. Компиляторы Microsoft имеют кучу CrtDebug, которая включена в отладочных сборках (но может установлены дополнительные элементы конфигурации). Я не уверен, что GCC имеет из коробки, но есть инструменты, с которыми я знаком мимоходом, такие как Valgrind и Electric Fence, которые могут помочь. Наконец, существует масса домашних библиотек отладки кучи, которые могут оказаться полезными (погуглите).

person Michael Burr    schedule 28.10.2009

Не могли бы вы предоставить свой оператор malloc()?

Кроме того, я хотел дважды проверить, что возвращаемое значение не равно нулю?

Помимо отсутствия памяти для выделения для начала, проблемы, с которыми я столкнулся при использовании malloc() или new, аналогичны характеру, который вы упомянули, где на самом деле возникает поврежденная куча. Обычно я находил «интересный» код в другом месте программы, выполняющий что-то вроде memcpy() с символьным буфером, вызывающим переполнение буфера и искаженное адресное пространство.

-bn

person bn.    schedule 28.10.2009