Per darti una migliore comprensione del motivo per cui questo accade, vorrei espandere un po 'la risposta di @ r-samuel-klatchko.
Quando chiami malloc
, ciò che sta realmente accadendo è un po 'più complicato che darti solo un pezzo di memoria con cui giocare. Sotto il cofano, malloc
mantiene anche alcune informazioni di pulizia sulla memoria che ti ha dato (soprattutto, le sue dimensioni), in modo che quando chiami free
, sappia cose come quanta memoria liberare. Queste informazioni vengono generalmente conservate subito prima che la posizione di memoria ti venga restituita da malloc
. Informazioni più esaurienti possono essere trovate su Internet ™ , ma l'idea (molto) di base è qualcosa del genere:
+------+-------------------------------------------------+
+ size | malloc'd memory +
+------+-------------------------------------------------+
^-- location in pointer returned by malloc
Basandosi su questo (e semplificando notevolmente le cose), quando si chiama malloc
, è necessario ottenere un puntatore alla parte successiva della memoria disponibile. Un modo molto semplice per farlo è guardare il bit di memoria precedente che ha ceduto e spostare i size
byte più in basso (o in alto) nella memoria. Con questa implementazione, si finisce con la memoria cercando qualcosa di simile dopo l'attribuzione p1
, p2
e p3
:
+------+----------------+------+--------------------+------+----------+
+ size | | size | | size | +
+------+----------------+------+--------------------+------+----------+
^- p1 ^- p2 ^- p3
Allora, qual è la causa del tuo errore?
Bene, immagina che il tuo codice scriva erroneamente oltre la quantità di memoria che hai allocato (o perché hai allocato meno del necessario come era il tuo problema o perché stai usando le condizioni al contorno sbagliate da qualche parte nel tuo codice). Supponiamo che il tuo codice scriva così tanti dati inp2
che inizia sovrascrivere ciò che è in p3
's size
campo. Alla successiva chiamata malloc
, esaminerà l'ultima posizione di memoria restituita, il campo delle dimensioni, si sposterà p3 + size
e inizierà ad allocare memoria da lì. Poiché il codice è stato sovrascritto size
, tuttavia, questa posizione di memoria non è più dopo la memoria allocata in precedenza.
Inutile dire che questo può rovinare il caos! Gli implementatori di malloc
hanno quindi inserito una serie di "asserzioni", o controlli, che cercano di fare un po 'di controlli di integrità per rilevare questo (e altri problemi) se stanno per accadere. Nel tuo caso particolare, queste affermazioni vengono violate e quindi si malloc
interrompono, dicendoti che il tuo codice stava per fare qualcosa che in realtà non dovrebbe fare.
Come affermato in precedenza, si tratta di una grossolana semplificazione, ma è sufficiente per illustrare il punto. L'implementazione glibc di malloc
è più di 5k righe e ci sono state notevoli quantità di ricerca su come costruire buoni meccanismi di allocazione dinamica della memoria, quindi non è possibile coprire tutto in una risposta SO. Si spera che questo ti abbia dato un'idea di cosa sta realmente causando il problema!