Чтобы дать вам лучшее понимание того, почему это происходит, я хотел бы немного расширить ответ @r-samuel-klatchko.
Когда вы вызываете malloc
, то, что на самом деле происходит, немного сложнее, чем просто предоставление вам куска памяти для игры. Под капотом malloc
также хранит некоторую служебную информацию о памяти, которую он вам предоставил (самое главное, ее размер), так что, когда вы вызываете free
, он знает такие вещи, как, сколько памяти нужно освободить. Эта информация обычно хранится непосредственно перед тем, как malloc
вернет вам адрес памяти. Более исчерпывающую информацию можно найти в Интернете™, но (очень) основная идея примерно такая:
+------+-------------------------------------------------+
+ size | malloc'd memory +
+------+-------------------------------------------------+
^-- location in pointer returned by malloc
Основываясь на этом (и значительно упрощая), когда вы вызываете malloc
, ему нужно получить указатель на следующую доступную часть памяти. Один очень простой способ сделать это — просмотреть предыдущий бит памяти, который он отдал, и переместить size
байтов дальше вниз (или вверх) в памяти. С этой реализацией ваша память будет выглядеть примерно так после выделения p1
, p2
и p3
:
+------+----------------+------+--------------------+------+----------+
+ size | | size | | size | +
+------+----------------+------+--------------------+------+----------+
^- p1 ^- p2 ^- p3
Итак, в чем причина вашей ошибки?
Что ж, представьте, что ваш код ошибочно записывает объем памяти, который вы выделили (либо потому, что вы выделили меньше, чем вам нужно, что было вашей проблемой, или потому, что вы используете неправильные граничные условия где-то в своем коде). Скажем, ваш код записывает так много данных в p2
, что он начинает перезаписывать то, что находится в поле size
p3
. Когда вы в следующий раз вызовете malloc
, он проверит последнюю возвращенную ячейку памяти, просмотрит поле своего размера, перейдет к p3 + size
и затем начнет выделение памяти оттуда. Однако, поскольку ваш код перезаписал size
, эта ячейка памяти больше не находится после ранее выделенной памяти.
Излишне говорить, что это может разрушить хаос! Поэтому разработчики malloc
ввели ряд «утверждений» или проверок, которые пытаются выполнить кучу проверок работоспособности, чтобы поймать эту (и другие проблемы), если они вот-вот произойдут. В вашем конкретном случае эти утверждения нарушаются и, таким образом, malloc
прерываются, сообщая вам, что ваш код собирался сделать что-то, чего он на самом деле делать не должен.
Как было сказано ранее, это грубое упрощение, но этого достаточно, чтобы проиллюстрировать суть. Реализация glibc malloc
состоит из более чем 5 тыс. строк, и было проведено значительное количество исследований о том, как создать хорошие механизмы динамического распределения памяти, поэтому охватить все это в ответе SO невозможно. Надеюсь, это дало вам некоторое представление о том, что на самом деле вызывает проблему!
person
Jon Gjengset
schedule
14.10.2013