Ich baue eine Anwendung zur Gestaltung von Fotobüchern. Die Anwendung dekomprimiert häufig JPEG-Bilder in speicherinterne Bitmap-Puffer. Die Größe der Bilder ist auf 100 Megapixel beschränkt (während sie normalerweise 15 Megapixel nicht überschreiten).
Manchmal schlägt die Speicherzuweisung für diese Puffer fehl: [[NSMutableData alloc] initWithLength:]
gibt zurück. nil
. Dies scheint in Situationen zu passieren, in denen der freie physische Speicher des Systems gegen Null geht.
Mein Verständnis der virtuelles Speichersystem in Mac OS X war das eine Zuweisung in einem 64-Bit-Prozess praktisch (sic) nicht scheitern kann. Es gibt 16 Exabyte Adressraum, von denen ich versuche, maximal 400 Megabyte auf einmal zuzuweisen. Theoretisch könnte ich 40 Milliarden dieser Puffer zuweisen, ohne an die harte Grenze des verfügbaren Adressraums zu stoßen. In der Praxis ist dieses Szenario natürlich nicht möglich, da der Swap-Bereich durch die Größe des Boot-Volumes begrenzt ist. In Wirklichkeit nehme ich nur sehr wenige dieser Zuweisungen vor (weniger als zehn).
Was ich nicht verstehe, ist die Tatsache, dass eine Zuweisung fehlschlägt, unabhängig davon, wie wenig physischer Speicher zu diesem Zeitpunkt vorhanden ist. Ich dachte, dass die Speicherzuweisung nicht scheitern würde, solange noch Auslagerungsspeicher vorhanden ist (da die Seiten zu diesem Zeitpunkt noch nicht einmal zugeordnet sind).
Die Anwendung wird vom Speicher gelöscht.
Edit :
Ich hatte Zeit, dieses Problem ein wenig genauer zu untersuchen, und hier sind meine Ergebnisse:
- Das Problem tritt nur bei einem Garbage-Collected-Prozess auf.
- Wenn die Zuweisung von
NSMutableData
scheitert, eine einfachemalloc
gelingt es immer noch, die gleiche Menge an Speicher zuzuweisen. - Der Fehler tritt immer dann auf, wenn sich der gesamte physische Speicher dem Wert Null nähert (Swapping steht bevor).
Ich nehme an NSData
verwendet NSAllocateCollectable
um die Zuweisung vorzunehmen, anstatt malloc
wenn es unter Garbage Collection läuft.
Meine Schlussfolgerung aus all dem ist, dass der Collector nicht in der Lage ist, große Teile des Speichers zuzuweisen, wenn der physische Speicher knapp ist. Was ich wiederum nicht verstehe.