2012-04-01 3 views
3

Die folgende Codezeile bewirkt, dass mein Programm in einer sehr seltsamen Art und Weise brechen ...Hat das Casting einer Adresse (ID) Nebenwirkungen? Ist Adresse 0xbfffe8d0 speziell? (Fest: Es ging mit _NSCallStackArray)

id foo = (id)0xbfffe8d0; 

Doch ist dies kein Problem:

int foo = (int)(id)0xbfffe8d0; 

Und auch das ist kein problem:

int magicAddr = 0xbfffe8d0; 
id foo = (id)magicAddr; 

WTF?

Wenn Sie nur diese Codezeile in eine bestimmte init-Methode einfügen, wird meine Iteration durch ein Array mit "NSGenericException: Collection wurde mutiert während der Aufzählung" fehlgeschlagen. Das Kommentieren der Linie bewirkt, dass die Ausnahme nicht auftritt. Dieser Code ist single-threaded. Das Verhalten ist deterministisch und hat sich immer wieder reproduziert und ist durchweg nicht reproduziert, wenn ich die Linie auszeichne. "foo" ist eine erfundene Variable und wird nie wieder referenziert. Kein anderer Code bezieht sich auf "foo".

Hat diese Linie einen Nebeneffekt? Hat das Casting einer Nummer zu einem (id) eine Nebenwirkung?

Weitere Details auf, was ich tat:

  • ich NSLog lief (@ "self =% p, super =% p", selbst, Super) und es ausgedruckt „self = 0xa83dc50, super = 0xbfffe8d0 ", führt mich zu fragen this question
  • Ich habe _NO_IDEA_ was dieser 0xbfffe8d0 Wert ist oder bedeutet.
  • Die Zeile, die ich eingefügt habe, befindet sich in einer Methode init2 für eine Klasse, die einen Verweis auf den NSEnumerator über die Auflistung hat, die die Ausnahme auslöst. Die Klasse mutiert die Sammlung NICHT oder hat sogar einen Verweis auf die Sammlung.

Der genaue Code: (entfernt, nicht relevant oder interessant)


OK, so kann ich immer noch nicht das Verhalten, das oben erklären. Ich kann nicht erklären, warum ein 4-Byte-Int auf dem Stapel in Ordnung ist, aber eine 4-Byte-ID ist crashville. Aber ich habe diesen Code ein paar hundert Mal laufen lassen, um alle Manor of Random Mist einzubauen, und ich konnte Abstürze mit anderen Werten und Aussagen auslösen. Immer deterministisch, aber kein klares oder erklärbares Muster für Dinge, die abgestürzt sind, oder Sachen, die nicht abstürzten. Bizarre Sachen, aber nicht das ultimative Problem.

Das eigentliche Problem? Die Sammlung stammt aus [NSThread callStackSymbols]. Das gibt _NSCallStackArray zurück. Dort lebt der echte Zebra. Diese Pseudo-Sammlung hat etwas Funkhaftes, aber ich konnte Ihnen nicht genau sagen, was genau.

Die Lösung?

[NSArray arrayWithArray: [NSThread callStackSymbols]] 

Bei dem Update wird keine Kombination von zufälligem Mist in meinem Code die Aufzählung Absturz auslösen. Hüte dich. Wenn Sie planen, die Aufrufstacksymbole zurückzugeben und sie als Array zu behandeln, MAKE A COPY.

Die Lektion? Wenn Sie [NSThread callStackSymbols] aufrufen und das Ergebnis wie ein Array behandeln möchten, MAKE A COPY und erhalten Sie ein echtes Array. Else, .... "Da sind Drachen" !!

Antwort

3

Nr. id ist ein typedef für einen Zeigertyp, und die Zuordnung zu einem Zeiger hat keine Nebenwirkungen. Sie haben einen anderen Fehler in Ihrem Code woanders, es ist unmöglich zu sagen, ohne mehr Code zu sehen.

0xbfffe8d0 ist ein Zeiger auf eine Adresse in Ihrem Stapel. Wenn sie ohne Optimierungen kompiliert wird, schreibt die Zuweisung den Wert 0xbffe8d0 in Ihren Stapel, aber dieser Wert wird nie irgendwo gelesen. Dies hat den Effekt, dass (a) die Stack-Frame-Größe dieser Funktion um 4 Bytes erhöht wird und (b) die Größe des Funktionscodes geändert und der gesamte nachfolgende Code versetzt wird. Wahrscheinlich führen diese Änderungen dazu, dass der Fehler an anderer Stelle in Ihrem Programm erscheint oder nicht erscheint.

+0

Ich würde sagen, alles, was Sie sagen, außer dass das Hinzufügen eines 4-Byte-Int keine Probleme verursacht, nur wenn ich auf (id) .... –

+0

ok, Sie haben Recht. Die Zebras waren woanders. Es gab aber immer noch Zebras .... –