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