Wenn ich benutze malloc()s und free()s zufällig, verschachtelt und mit unterschiedlichen Größen, irgendwann wird der Speicher fragmentiert, weil diese Operationen eine große Liste kleiner Speicherbereiche hinterlassen, die nicht zusammenhängend sind und daher nicht als ein größeres Stück allokiert werden können.
Ein paar Fragen dazu:
Wenn dies ziemlich oft geschieht, wird der Speicher gezwungen, und dann fragmentiert zu werden alle diese Speicherbereiche sind free()d, kann ich davon ausgehen, dass diese freien Bereiche wieder auf ihre ursprüngliche, zusammenhängende Größe verkettet sind?
Wenn ich immer a mache malloc() gefolgt von free() für den gleichen Speicher und niemals diese Aufrufe verschachteln, ist der Speicher auch in diesem Szenario fragmentiert, wenn zugewiesene/freigegebene Größen immer unterschiedlich sind?
All dies ist implementierungsabhängig. Aber ja, ein guter Speichermanager wird zusammenhängende freie Speicherbereiche verketten. Und ja, wenn Sie a malloc gefolgt von einem free und Sie rufen keine Bibliotheksfunktionen auf, die aufrufen malloc dazwischen , dann sollte keine Fragmentierung auftreten.
– Jabberwocky
12. Mai 2016 um 12:14 Uhr
Sie können Valgrind mit Ihrem Programm ausführen valgrind.org und prüfen Sie auf Datenausrichtungsfehler und Speicherlecks.
– Niklas Rosenkranz
12. Mai 2016 um 12:20 Uhr
Es ist ziemlich schwierig, einen 64-Bit-Adressraum zu fragmentieren. Sicher, Sie können es leicht bis zu dem Punkt fragmentieren, an dem Sie kein 10-TB-Objekt mehr zuweisen können, aber Sie hatten wahrscheinlich sowieso keine 10-TB-RAM.
– MSalter
12. Mai 2016 um 12:56 Uhr
1. nein. 2. nein. Wenn der Speicherzuordner ASLR ausführt, kann er aktiv vermeiden, so vorhersehbar zu sein, wie Sie es möchten. Die Lösung besteht darin, eine Architektur mit einem großen Adressraum zu verwenden und die Fragmentierung zu ignorieren, mit 64-Bit-Zeigern und den heutigen großen Speichergrößen ist die Fragmentierung meistens ein Problem von gestern, es sei denn, Sie haben eine sehr spezifische Anwendung.
– Kunst
12. Mai 2016 um 13:02 Uhr
Wie würde das überhaupt funktionieren? C bietet keine Garbage Collection, weniger Speicherplatzverdichtung. Es kann einfach nicht, da es keine Informationen darüber gibt, wo Zeiger auf Objekte existieren.
Die Reihenfolge und Kontinuität des Speichers, der durch aufeinanderfolgende Aufrufe der Funktionen aligned_alloc, calloc, malloc und realloc zugeordnet wird, ist nicht spezifiziert.
Wie auch immer, Sie haben zwei Möglichkeiten zur Auswahl:
Vertrauen Sie voll und ganz auf die Speicherverwaltungsfunktionen der Bibliothek.
Schreiben Sie Ihre eigenen Speichermanager, wenn Sie sind Wirklich zuversichtlich.
An deiner Stelle würde ich auf jeden Fall auf die vorhandenen Funktionen vertrauen, denn moderne Umsetzungen sind super smart.
Da die Frage (auch) mit C++ gekennzeichnet ist, schließen sich die beiden Möglichkeiten nicht gegenseitig aus. Sie können überschreiben operator new auf Klassenbasis.
– MSalter
12. Mai 2016 um 12:51 Uhr
sjsam
Gem ISO/IEC 9899:201x -> 7.22.3
Die Reihenfolge und Kontinuität des Speichers, der durch aufeinanderfolgende Aufrufe der Funktionen aligned_alloc, calloc, malloc und realloc zugeordnet wird, ist nicht spezifiziert.
Ein guter Speichermanager wird in der Lage sein, das Problem bis zu einem gewissen Grad anzugehen. Es gibt jedoch andere Aspekte wie Datenabgleich [1] was zu interner Fragmentierung führt.
Was könnten Sie tun, wenn Sie sich auf die integrierte Speicherverwaltung verlassen?
Verwenden Sie einen Profiler – z. B. Valgrind – mit Speicherprüfungsoption, um den Speicher zu finden, der nach der Verwendung nicht freigegeben wird. Beispiel:
valgrind --leak-check=yes myprog arg1 arg2
Befolgen Sie gute Praktiken. Beispiel – Wenn Sie in C++ beabsichtigen, dass andere von Ihrer polymorphen Klasse erben, können Sie ihren Destruktor als virtuell deklarieren.
All dies ist implementierungsabhängig. Aber ja, ein guter Speichermanager wird zusammenhängende freie Speicherbereiche verketten. Und ja, wenn Sie a
malloc
gefolgt von einemfree
und Sie rufen keine Bibliotheksfunktionen auf, die aufrufenmalloc
dazwischen , dann sollte keine Fragmentierung auftreten.– Jabberwocky
12. Mai 2016 um 12:14 Uhr
Sie können Valgrind mit Ihrem Programm ausführen valgrind.org und prüfen Sie auf Datenausrichtungsfehler und Speicherlecks.
– Niklas Rosenkranz
12. Mai 2016 um 12:20 Uhr
Es ist ziemlich schwierig, einen 64-Bit-Adressraum zu fragmentieren. Sicher, Sie können es leicht bis zu dem Punkt fragmentieren, an dem Sie kein 10-TB-Objekt mehr zuweisen können, aber Sie hatten wahrscheinlich sowieso keine 10-TB-RAM.
– MSalter
12. Mai 2016 um 12:56 Uhr
1. nein. 2. nein. Wenn der Speicherzuordner ASLR ausführt, kann er aktiv vermeiden, so vorhersehbar zu sein, wie Sie es möchten. Die Lösung besteht darin, eine Architektur mit einem großen Adressraum zu verwenden und die Fragmentierung zu ignorieren, mit 64-Bit-Zeigern und den heutigen großen Speichergrößen ist die Fragmentierung meistens ein Problem von gestern, es sei denn, Sie haben eine sehr spezifische Anwendung.
– Kunst
12. Mai 2016 um 13:02 Uhr
Wie würde das überhaupt funktionieren? C bietet keine Garbage Collection, weniger Speicherplatzverdichtung. Es kann einfach nicht, da es keine Informationen darüber gibt, wo Zeiger auf Objekte existieren.
– zu ehrlich für diese Seite
12. Mai 2016 um 13:09 Uhr