Warum wird eine __block Variable in den Heap verschoben, BEVOR der Block kopiert wird? [geschlossen]

8

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%     
jcccn 26.02.2013, 05:49
quelle

3 Antworten

3

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.

    
CodaFi 26.02.2013 07:06
quelle
2

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.

    
newacct 26.02.2013 08:49
quelle
0

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 Ссылка

    
gelosie 26.02.2013 14:04
quelle