C (und C ++) enthalten eine Familie dynamischer Speicherzuordnungsfunktionen, von denen die meisten intuitiv benannt und einem Programmierer mit einem grundlegenden Verständnis von Speicher leicht erklärt werden können. malloc()
reserviert einfach Speicher, während calloc()
etwas Speicher zuweist und es eifrig löscht. Es gibt auch realloc()
und free()
, die ziemlich selbsterklärend sind.
Die Hilfeseite für malloc()
erwähnt auch valloc()
, wodurch ( size
) Bytes am Seitenrand ausgerichtet werden.
Leider ist mein Hintergrund in den Feinheiten der unteren Ebenen nicht gründlich genug; Welche Auswirkungen hat das Zuweisen und Verwenden von Speicher mit Seitenrandausrichtung, und wann ist dies im Gegensatz zu regulären malloc()
oder calloc()
?
Die Hilfeseite für valloc
enthält eine wichtige Anmerkung:
Die Funktion valloc () erschien in 3.0BSD. Es ist in 4.3BSD als veraltet und in SUSv2 als veraltet dokumentiert. Es erscheint nicht in POSIX.1-2001.
valloc
ist veraltet und nicht standardisiert - um Ihre Frage zu beantworten, wäre es niemals angemessen, in neuem Code zu verwenden.
Es gibt zwar einige Gründe dafür, ausgerichteten Speicher zuzuweisen - diese Frage listet ein paar auf Gute - es ist normalerweise besser, wenn der Speicherzuordner weiß, welches Speicherbit er Ihnen geben soll. Wenn Sie sicher sind, dass Ihr frisch zugewiesener Speicher an etwas ausgerichtet sein muss, verwenden Sie stattdessen aligned_alloc
(C11) oder posix_memalign
(POSIX).
Zuordnungen mit Seitenausrichtung werden normalerweise nicht für die Geschwindigkeit ausgeführt - sie sind, weil Sie einige Funktionen der MMU Ihres Prozessors nutzen möchten, die normalerweise mit Seitengranularität arbeiten.
Ein Beispiel ist, wenn Sie mprotect(2)
verwenden möchten, um die Zugriffsrechte für diesen Speicher zu ändern. Angenommen, Sie möchten beispielsweise einige Daten in einem Speicherbereich speichern und dann nur lesen, sodass ein fehlerhafter Teil Ihres Programms, der versucht, dort zu schreiben, einen segfault auslöst. Da mprotect(2)
die Berechtigungen nur Seite für Seite ändern kann (da dies die zugrunde liegende CPU-Hardware erzwingen kann), sollte der Block, in dem Sie Ihre Daten speichern, besser auf Seiten ausgerichtet sein und seine Größe sollte ein Vielfaches der Seitengröße sein. Andernfalls enthält der schreibgeschützte Bereich möglicherweise andere, nicht verwandte Daten, die noch geschrieben werden müssen.
Oder vielleicht erstellen Sie ausführbaren Code im Speicher und möchten ihn später ausführen. Speicher, den Sie standardmäßig zuweisen, ist wahrscheinlich nicht so eingestellt, dass Codeausführung erlaubt ist, daher müssen Sie mprotect
verwenden, um ihm die Ausführungsberechtigung zu geben. Auch dies muss mit Seitengranularität erfolgen.
Ein anderes Beispiel ist, wenn Sie jetzt Speicher reservieren möchten, aber später mmap
noch etwas hinzufügen möchten.
Im Allgemeinen würde ein Bedarf an seitenausgerichtetem Speicher sich auf eine Anwendung auf ziemlich niedriger Ebene beziehen, die oft etwas Systemspezifisches beinhaltet. Wenn du es brauchst, würdest du es wissen. (Und wie erwähnt, sollten Sie es nicht mit valloc
, sondern mit posix_memalign
oder vielleicht einem anonymen mmap
zuweisen.)
Zunächst ist valloc
veraltet und stattdessen sollte memalign
verwendet werden.
Zweitens ist es überhaupt nicht Teil des C (C ++) Standards.
Es ist eine spezielle Zuweisung, die auf _SC_PAGESIZE
boundary ausgerichtet ist.
Wann ist es nützlich, es zu benutzen? Ich schätze nie, es sei denn, Sie haben eine bestimmte Anforderung auf niedrigem Niveau. Wenn Sie es brauchen, würden Sie es brauchen, da es selten nützlich ist (vielleicht nur, wenn Sie einige Mikro-Optimierungen ausprobieren oder geteilten Speicher zwischen Prozessen erstellen).
Die offensichtliche Antwort lautet, dass es angemessen ist, valloc zu verwenden, wenn malloc für das Anwendungsmuster der (virtuellen) Speicher ungeeignet (weniger effizient) ist und valloc besser geeignet (effizienter) ist. Dies hängt vom Betriebssystem und den Bibliotheken und der Architektur und Anwendung ab ...
malloc hat herkömmlicherweise tatsächlich Speicher aus freigegebenem Speicher zugewiesen, falls verfügbar, und durch Erhöhen des brk-Punkts, falls nicht, in diesem Fall wird es aus Sicherheitsgründen vom Betriebssystem gelöscht.
calloc in einer dummen Implementierung führt ein malloc aus und löscht den Speicher dann (neu), während eine intelligente Implementierung es vermeiden würde, neu zugewiesenen Speicher neu zu laden, der automatisch vom Betriebssystem gelöscht wird.
valloc bezieht sich auf virtuellen Speicher. In einem virtuellen Speichersystem, das das Dateisystem verwendet, können Sie eine große Menge an Speicher oder Dateibereich / Speicherbereich zuweisen, sogar mehr als physischen Speicher, und es wird nach Seiten eingetauscht, so dass die Ausrichtung ein Faktor ist. In Unix wird die Erstellung einer Datei einer bestimmten Datei und das Hinzufügen / Löschen von Seiten mit Hilfe von Inodes durchgeführt, um die Datei zu definieren, sie behandelt jedoch nicht die tatsächlichen Plattenblöcke, bis sie benötigt wird. In diesem Fall werden sie gelöscht. Ich würde also erwarten, dass ein valloc-System die Größe des Datensegment-Swaps erhöht, ohne physische oder Swap-Seiten zuzuordnen, oder eine for-Schleife ausführt, um alles zu löschen, da das Datei- und Paging-System dies nach Bedarf erledigt. Daher sollte valloc viel schneller sein als malloc. Aber wie bei calloc, wie bestimmte idiotensynkratische * x / C-Aromen es tun, liegt es an ihnen, und die valloc-man-Seite ist völlig unzufrieden mit diesen Erwartungen.
Traditionell wurde dies mit brk / sbrk implementiert. Natürlich gibt es in einem virtuellen Speichersystem, ob ein seitengestütztes oder ein segmentiertes System, keinen wirklichen Bedarf für irgendeinen dieser brk / sbrk-Kram und es genügt, einfach den letzten Ort in eine Datei oder einen Adressraum zu schreiben, um sich auf diesen zu erstrecken Punkt.
Bei der Zuweisung zu den Seitengrenzen ist das normalerweise nicht etwas, was der Benutzer will oder braucht, sondern ist normalerweise etwas, das das System will oder braucht.
Eine (wahrscheinlich teurere) Methode zur Simulation von valloc besteht darin, die Seitengrenze zu bestimmen und dann aligned_alloc oder posix_memign mit dieser Ausrichtungsspezifikation aufzurufen.
Die Tatsache, dass valloc veraltet ist oder entfernt wurde oder in manchen Betriebssystemen nicht benötigt wird, bedeutet nicht, dass es in anderen noch immer nützlich und für die beste Effizienz erforderlich ist. Wenn es veraltet oder entfernt wurde, würde man hoffen, dass es Ersatz gibt, die genauso effizient sind (aber ich würde nicht darauf wetten und könnte tatsächlich meinen eigenen malloc Ersatz geschrieben haben).
In den letzten 40 Jahren haben sich die Kompromisse zwischen echtem und (einmal erfundenem) virtuellem Speicher periodisch geändert, und Mainstream-Betriebssysteme tendieren eher zu Schnickschnack als zu Effizienz, mit Programmierern, die keine (Zeit- oder Raum-) Effizienz haben ein wichtiger Imperativ. In den eingebetteten Systemen ist die Effizienz kritischer, aber selbst dort wird die Effizienz oft nicht gut durch das Standard-Betriebssystem und / oder die Standard-Tools unterstützt. Aber im Zweifelsfall können Sie Ihren eigenen malloc-Ersatz für Ihre Anwendung rollen, der das tut, was Sie brauchen, anstatt davon abhängig zu sein, was ein anderer geweckt hat und entschieden hat / zu implementieren oder rückgängig zu machen.
Die richtige Antwort ist also, dass Sie nicht unbedingt valloc oder malloc oder calloc oder irgendeinen der Ersetzungen verwenden wollen, die Ihre aktuelle Subversion eines Betriebssystems bietet.
Tags und Links c memory-management malloc