Um Ihnen ein besseres Verständnis dafür zu geben, warum dies geschieht, möchte ich die Antwort von @ r-samuel-klatchko etwas näher erläutern.
Wenn Sie anrufen malloc
, ist das, was wirklich passiert, etwas komplizierter, als Ihnen nur einen Teil des Gedächtnisses zum Spielen zu geben. Unter der Haube werden malloc
auch einige Haushaltsinformationen über den Speicher gespeichert, den Sie erhalten haben (vor allem über die Größe), sodass er beim Anrufen beispielsweise free
weiß, wie viel Speicher freigegeben werden muss. Diese Informationen werden normalerweise direkt vor dem Speicherort gespeichert, den Sie von erhalten haben malloc
. Ausführlichere Informationen finden Sie im Internet ™ , aber die (sehr) Grundidee ist ungefähr so:
+------+-------------------------------------------------+
+ size | malloc'd memory +
+------+-------------------------------------------------+
^-- location in pointer returned by malloc
Darauf aufbauend (und die Dinge stark vereinfachend) muss beim Aufrufen malloc
ein Zeiger auf den nächsten verfügbaren Teil des Speichers abgerufen werden. Eine sehr einfache Möglichkeit, dies zu tun, besteht darin, das zuvor verschenkte Speicherbit zu betrachten und die size
Bytes im Speicher weiter nach unten (oder oben) zu verschieben. Mit dieser Implementierung, beenden Sie mit Ihrem Gedächtnis auf etwas so aussehen , nachdem die Zuweisung p1
, p2
und p3
:
+------+----------------+------+--------------------+------+----------+
+ size | | size | | size | +
+------+----------------+------+--------------------+------+----------+
^- p1 ^- p2 ^- p3
Was verursacht Ihren Fehler?
Stellen Sie sich vor, Ihr Code schreibt fälschlicherweise über die von Ihnen zugewiesene Speichermenge hinaus (entweder weil Sie weniger zugewiesen haben, als Sie als Problem benötigt haben, oder weil Sie irgendwo in Ihrem Code die falschen Randbedingungen verwenden). Sagen Sie den Code schreibt so viele Daten , p2
dass es beginnt zu überschreiben , was in ist p3
‚s size
Feld. Wenn Sie jetzt das nächste Mal anrufen malloc
, wird der zuletzt zurückgegebene Speicherort angezeigt, das Größenfeld angezeigt, der p3 + size
Speicherplatz verschoben und von dort aus mit der Zuweisung von Speicher begonnen. Da Ihr Code jedoch überschrieben size
wurde, befindet sich dieser Speicherort nicht mehr hinter dem zuvor zugewiesenen Speicher.
Unnötig zu sagen, dass dies Chaos zerstören kann! Die Implementierer von malloc
haben daher eine Reihe von "Behauptungen" oder Überprüfungen abgegeben, die versuchen, eine Reihe von Überprüfungen der geistigen Gesundheit durchzuführen, um dies (und andere Probleme) zu erkennen, wenn sie in Kürze eintreten. In Ihrem speziellen Fall werden diese Behauptungen verletzt und daher malloc
abgebrochen, um Ihnen mitzuteilen, dass Ihr Code etwas tun würde, was er eigentlich nicht tun sollte.
Wie bereits erwähnt, handelt es sich um eine grobe Vereinfachung, die jedoch ausreicht, um den Punkt zu veranschaulichen. Die glibc-Implementierung von malloc
umfasst mehr als 5.000 Zeilen, und es wurden umfangreiche Untersuchungen zum Aufbau guter dynamischer Speicherzuweisungsmechanismen durchgeführt, sodass es nicht möglich ist, alles in einer SO-Antwort abzudecken. Hoffentlich haben Sie dadurch einen Überblick darüber bekommen, was das Problem wirklich verursacht!