Absturz auf dem iOS-Gerät, wenn ein Zeiger rückgängig gemacht wird, der von NSCoders decodeBytesForKey zurückgegeben wurde

8

Ich habe einen ungewöhnlichen Crasher mit NSCoder gefunden, wenn ich den Apple LLVM Compiler 3.0 benutze und mit -O3 kompiliert habe. Es stürzt nur auf Geräten ab. Ich habe ein iPhone 4 mit iOS 5, ein iPad 2 mit iOS 5 und ein iPad 1 mit iOS 4 getestet. Alle sind identisch abgestürzt. Hier ist der relevante Codeabschnitt:

%Vor%

Und hier ist was ein BBPointI32 ist:

%Vor%

EXC_BAD_ACCESS passiert, wenn data dereferenziert wird. Dies ist nicht ein Nullzeigerproblem. Wenn ich GDB anschließe, kann ich sehen, dass Länge 8 ist, sizeof (BBPointI) ist auch 8 und die Daten sind korrekt.

Wenn ich auf die Demontage schaue, passiert der Absturz auf:

%Vor%

Was gut aussieht. r0 enthält 0xb546e, die Adresse von data . Wenn ich diesen Speicher überprüfe, kann ich sehen, dass er die Daten enthält, die ich erwarte. Für alle, die daran interessiert sind, enthält r2 72 (nicht sicher, was das ist) und r3 enthält 8 (höchstwahrscheinlich der Wert von length ).

Kann jemand etwas zu diesem Thema sagen?

    
Matt Comi 11.10.2011, 16:07
quelle

4 Antworten

10

ldrd benötigt die Adresse, um 8-Byte ausgerichtet zu sein. Das * (BBPointI32 *) -Datenidiom ist nicht sicher, da Daten nicht 8-Byte-ausgerichtet sind. Verwenden Sie stattdessen memcpy, um die Bytes in die Struktur zu bekommen.

    
biorhythmist 11.10.2011, 17:10
quelle
4

Verwenden Sie ARC? In diesem Fall glaube ich, dass der Compiler frei ist, decoder nach dem Aufruf von decodeBytesForKey: freizugeben (also den Puffer freizugeben, auf den der Rückgabewert zeigte).

Es ist das gleiche Interior Pointer Problem Garbage Collection hat . Sie können CFRetain / CFRelease Ihren Decoder verlängern, um seine Lebensdauer zu verlängern, oder fügen Sie einfach einen [decoder self] später in die Methode ein, um ihn bis zu diesem Punkt am Leben zu erhalten.

Ich vermute, dass Sie dieses Problem möglicherweise lösen können, indem Sie decoder mit __attribute__((objc_precise_lifetime)) kommentieren, aber ich verstehe dieses Attribut ist etwas verschwommen.

    
Andy Matuschak 11.10.2011 16:44
quelle
3

Ihr Beispiel lässt viele Variablen von jedem potenziellen Helfer in Frage gestellt werden. Zum Beispiel: Was, wenn es etwas Unkonventionelles gibt? Wird der Speicher korrekt verwaltet?

Ich konnte den angezeigten Absturz reproduzieren und kann bestätigen, dass er nur auftritt, wenn -O3 aktiviert ist und nicht, wenn z. Keine wird zur Optimierung ausgewählt. Hier ist eine Reduzierung des Absturzcodes, der externe Variablen wie die Speicherverwaltung der Codierer usw. eliminiert. Beachten Sie, dass der folgende Code alle Objekte absichtlich speichert, um die Möglichkeit auszuschließen, dass der Absturz mit einer versehentlichen Überfreigabe oder einer Seitwärtsbewegung zusammenhängt. Effekt der Verwendung von ARC, wie von Andy in einer anderen Antwort vorgeschlagen:

%Vor%

Ich denke, dies gibt eine prägnantere Beschreibung des Problems, dass jeder, der helfen möchte, als Grundlage für das Tauchen verwenden kann. Mein Vorwurf ist, dass dies ein Optimierungsfehler in LLVM 3.0 ist, aber vielleicht jemand anderes bessere Theorie über das, was vor sich geht.

Ein Punkt, den Sie in Ihrer Frage nicht erwähnt haben, den ich aber beim Absturz auf meinem Gerät bemerkt habe, ist der Fehler, der von einem EXC_ARM_DA_ALIGN-Fehler als Grund für die schlechte Zugriffsausnahme begleitet wird. Ich habe einen Blogpost gegoogelt, der auf die gleichen Symptome anspielt und wahrscheinlich zum Absturz führt, wie Sie es hier sehen:

Ссылка

In der Tat, indem Sie die Zeile über

ändern %Vor%

bis

%Vor%

Das Absturzverhalten scheint gemildert zu sein und der Code verhält sich wie erwartet.

    
danielpunkass 11.10.2011 17:01
quelle
1

Ich bin zu diesem Thread gekommen, google "EXC_ARM_DA_ALIGN" und "EXC_BAD_ACCESS". Keine der anderen Antworten hat mir geholfen, da dieser Fehler wegen etwas relativ Einfachem auftrat. Ich hatte geschrieben:

%Vor%

d. Ich hatte ein @ vor einem String-Literal weggelassen. Das Zurücksetzen löste den Fehler.

    
coco 21.11.2012 21:14
quelle

Tags und Links