Ich weiß, dass eine Variable __block
vom Stapel auf den Heap verschoben wird, wenn ein Block, der darauf zugreift, kopiert wurde. Aber der folgende Testcode zeigt mir, dass die Variable __block
in den Heap verschoben wird, bevor der Block kopiert.
Das heißt, die vier Ausgaben sind: stack = & gt; Heap = & gt; Heap = & gt; Heap, was nicht mein erwartetes Ergebnis ist: stack = & gt; Stapel = & gt; Stapel = & gt; Haufen.
Könnte mich jemand aufrichten?
%Vor%Lassen Sie mich das vorwegnehmen, indem ich sage: Blöcke sind komisch.
Nun, wenn Sie beginnen, haben Sie eine Variable x deklariert und sie mit __block
als Präfix versehen. Was zum Teufel ist __block
auf jeden Fall? Für Objekte, die im lexikalischen Gültigkeitsbereich des Blocks erfasst werden, sind die Variablen -retain
'ed, um sicherzustellen, dass sie bei der Ausführung des Blocks vorhanden sind. Aber für primitive Variablen sichern Blöcke ihre Werte, indem sie gezwungen werden, sie durch const
-Wert statt durch Referenz zu übergeben. Durch das Voranstellen von __block
haben Sie dem Compiler freie Hand gegeben, Ihre Variable "magisch" vom Stapel zum Heap zu bewegen, wenn der Block kopiert wird. Um es klar zu stellen, sind __block
Variablen tatsächlich Stapel zugeordnet, aber sie werden in den Heap ( malloc()
'd) verschoben, wenn der Block kopiert wird.
Aber was ist mit den seltsamen Änderungen an der Position von x? Nun, zurück zu __block
nochmal. Da Sie keine const
-Referenz auf x wie eine normale Variable verwenden, verwenden Blöcke einen (leicht ärgerlichen) Trick: Ein Block erzeugt einen Zeiger auf eine beliebige __block
-Variable, und wenn diese Variable mutiert ist, wird sie dereferenziert. Ta da! Ihre Variable wurde nicht vom Stapel auf den Heap verschoben, der Block hat lediglich den Zeiger auf den Zeiger dereferenziert und in den Speicher verschoben!
Sie sind wirklich verwirrt darüber, wo und wann Ihre Variablen bewegt werden. Ihr Beispiel protokolliert die korrekten Werte.
Ihre erwartete Ausgabe basiert auf Ihrer Annahme, dass der Block erst in Schritt 3-4 kopiert wird. Dies wird jedoch in den Blocks-Spezifikationen nicht garantiert.
Ja, der Block wird spätestens kopiert, wenn Sie explizit -copy
aufrufen. Aber warum kann es nicht früher kopiert werden? Es ist nie falsch einen Block früher zu kopieren. Daher ist es nicht definiert, wann genau ein Block kopiert wird, und Sie sollten nicht darauf angewiesen sein.
Einige neuere Versionen des Compilers unter ARC können konservativ sein und einen Block sofort nach der Erstellung kopieren. Daran ist nichts falsch. Wenn es das tut, wäre es ein Implementierungsdetail und andere Compiler oder zukünftige Versionen könnten etwas anderes machen.
Ich habe die gleiche Frage gestellt bei In Objective-C mit ARC, was macht der Compiler, wenn ich einen Block definiere?
Falls Sie den Code in ARC ausführen
In ARC,
Blockvariablen des Typs des beibehaltenen Objekteigentümers werden von der entfernt Stapeln durch Initialisieren der Heap - Kopie mit dem Ergebnis der Bewegung von der Stapelkopie.
in Ссылка
Tags und Links objective-c ios objective-c-blocks heap-memory