Чтобы вы лучше понимали, почему это происходит, я хотел бы немного расширить ответ @ 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
что он начинает перезаписывать , что в p3
«s size
поле. Когда вы теперь вызовете следующий вызов malloc
, он будет смотреть на последнее возвращенное место в памяти, смотреть на его поле размера, переместиться p3 + size
и затем начать выделение памяти оттуда. Однако, поскольку ваш код был перезаписан size
, эта ячейка памяти больше не находится после ранее выделенной памяти.
Излишне говорить, что это может нанести серьезный ущерб! Поэтому разработчики malloc
внедрили ряд «утверждений» или проверок, которые пытаются выполнить несколько проверок работоспособности, чтобы отловить это (и другие проблемы), если они вот-вот произойдут. В вашем конкретном случае эти утверждения нарушаются и, таким образом, malloc
прерываются, сообщая вам, что ваш код собирался сделать что-то, чего на самом деле делать не должно.
Как было сказано ранее, это грубое упрощение, но его достаточно, чтобы проиллюстрировать суть дела. Реализация glibc malloc
состоит из более чем 5 тыс. Строк, и было проведено значительное количество исследований о том, как построить хорошие механизмы распределения динамической памяти, поэтому охватить все это в SO-ответе невозможно. Надеюсь, это дало вам некоторое представление о том, что на самом деле вызывает проблему!