La frammentazione viene dalla memoria che è inutilizzabile. L'allocazione dinamica è simile a giocare a Tetris: se giochi velocemente, finisci con buchi (frammentazione) e non puoi prevedere quale tipo di blocco cadrà dopo. Con l'allocazione dinamica, non puoi prevedere quando e quale memoria sarà liberata - immagina di giocare a Tetris dove i blocchi scompaiono casualmente! Ricorda inoltre che l'allocazione dinamica potrebbe richiedere l'allocazione di blocchi di dimensioni variabili: Tetris implicherebbe polynominos anziché tetrominos!
Un po 'sulle tecniche di allocazione dinamica:
Il modo in cui hai descritto è l'allocazione dei blocchi a dimensione fissa. Di solito è implementato come lista gratuita . Il problema con questo metodo è che non può allocare blocchi di dimensioni diverse e può portare a un cattivo comportamento nella cache.
Uno dei modi più semplici per implementare l'allocazione dinamica è allocazione della memoria buddy - implementato come un albero binario che soddisfa l'heap proprietà. Il problema con questo metodo è che ha una frammentazione interna. La frammentazione interna deriva dall'uso di tecniche che utilizzano blocchi predeterminati, in genere poteri di 2. Ciò significa che allocare 150 byte allocerebbe effettivamente un blocco di 256, sprecando 106 byte a causa della frammentazione interna.
Altri metodi cercano di ridurre al minimo la frammentazione, come allocazione lastre . L'allocazione delle lastre viene principalmente utilizzata per i kernel, poiché è stata progettata per allocare piccoli oggetti: non è l'ideale per malloc per scopi generici.
Comunque, il punto a cui sto andando è che tutto dipende dal tipo di allocazioni che stai facendo. I sistemi operativi non sanno quale metodo di allocazione sarebbe il migliore per un programma, ed è per questo che ne scelgono uno che bilancia la velocità con la frammentazione. È quasi impossibile avere la frammentazione 0 senza spingere continuamente i dati, è solo la natura dell'allocazione dinamica.