Frage

Entweder mein Debugger gebrochen ist oder es ist etwas grundlegend, dass ich nicht verstehen.

Ich habe einig sehr grundlegenden Code in einem sehr einfachen Befehlszeilenprogramm, das sollte zum Absturz bringen. Es ist jedoch nicht abstürzt.

int main (int argc, const char * argv[])
{
    NSString *string = [[NSString alloc] initWithString:@"Hello"];

    [string release];

    NSLog(@"Length: %d", [string length]);

    return 0;
}

Die Log-Anweisung druckt „Länge: 5“, wie Sie für eine gültige Zeichenfolge erwartet. Allerdings sollte die Zeichenfolge, die von diesem Punkt ausgeplant werden und ein exec_bad_access Fehler soll geworfen werden.

Ich habe diesen Code mit dem Debugger versucht angebracht und ohne den Debugger angeschlossen - beide das gleiche Ergebnis. Ich habe auch aktiviert (und deaktiviert) NSZombie, die keine Wirkung zu haben scheint (ich zunächst dachte, das ist das Problem war, da NSZombie Objekte nie freigegeben werden - aber es funktioniert Absturz noch nicht mit NSZombie deaktiviert).

Ich habe Haltepunkte setzen in meiner lokalen .gdbinit Datei auf Dinge wie -[NSException raise] und objc_exception_throw zu brechen. Ich habe auch auf vielen Methoden auf NSZombie um Haltepunkte zu setzen, sie zu fangen.

fb -[NSException raise]
fb -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:]
fb -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]

#define NSZombies
# this will give you help messages.  Set to NO to turn them off.
set env MallocHelp=YES
# might also be set in launch arguments.
set env NSZombieEnabled=YES
set env NSDeallocateZombies=NO
set env MallocCheckHeapEach=100000
set env MallocCheckHeapStart=100000
set env MallocScribble=YES
set env MallocGuardEdges=YES
set env MallocCheckHeapAbort=1

set env CFZombie 5

fb -[_NSZombie init]
fb -[_NSZombie retainCount]
fb -[_NSZombie retain]
fb -[_NSZombie release]
fb -[_NSZombie autorelease]
fb -[_NSZombie methodSignatureForSelector:]
fb -[_NSZombie respondsToSelector:]
fb -[_NSZombie forwardInvocation:]
fb -[_NSZombie class]
fb -[_NSZombie dealloc]

fb szone_error
fb objc_exception_throw

Mit diesen Haltepunkte setzen und NSZombie aktiviert ist, sollte ich so etwas wie [NSString length]: message sent to deallocated instance 0x100010d39 bekommen auf der Konsole ausgegeben, aber ich weiß das nicht sehen. Ich sehe die NSLog Drucken der Länge als 5.

Ich sehe ein ähnliches Verhalten mit anderen Klassen wie NSURL und NSNumber. Aber einige Klassen abstürzen wie erwartet, wie NSError und NSObject.

Hat dies etwas mit Klasse-Cluster zu tun? Haben sie die gleichen Regeln in Bezug auf die Speicherverwaltung nicht folgen?

Wenn Klasse Cluster nicht auf dieses Problem verwandt sind, die einzige andere gemeinsames Merkmal konnte ich war sehen, dass die Klassen, die auf diese Weise nicht abstürzen sind alle gebührenfrei mit einem Gegenstück Core Foundation überbrückt. Könnte das etwas damit zu tun?

War es hilfreich?

Lösung

retain / release ist ein Vertrag zwischen dem API und dem Programmierer, dass, wenn Sie der Regel folgen, ist es nicht zum Absturz bringen. Der Vertrag garantiert nicht, dass, wenn Sie die Regel nicht folgen, tut es Absturz!

In diesem Fall

[[NSString alloc] initWithString:@"Hello"]

liefert nur das gleiche Objekt wie @"Hello" als Optimierung. Die Konstante NSString wird nie freigegeben; als eine Optimierung, retain und release ist (glaube ich) ignoriert. Aus diesem Grunde ist es nicht zum Absturz bringen.

Sie können meine Vermutung überprüfen, indem Sie den Zeigerwert von @"Hello" und string verglichen wird.

Andere Tipps

Dies ist ein ausgezeichnetes Beispiel dafür, warum behalten zählt ein ziemlich nutzloses Debugging-Tool ist. Es ist ein Irrtum anzunehmen, -retain und -release immer hinzufügen oder 1 entfernen zählen behalten und dass die Beibehaltungszähler ist, was denken Sie, sollte es sein.

Versuchen

NSString *string = [[NSString alloc] initWithFormat:@"Hello %d", argc];

Das sollten Sie eine Zeichenfolge geben, die eher wie die Art und Weise verhalten Sie erwarten, da Sie nicht Ihre Zeichenfolge aus einer Kompilierung Konstante initialisiert. Aber seien Sie gewarnt, mit Zombies aktiviert, können Sie das Verhalten, das Sie erwarten, bekommen aber ohne Zombies, die NSLog kann gut funktionieren. Obwohl die Zeichenfolge die Daten in dem Objekt freigegeben wurde, ist immer noch da im Speicher einen „Geist“ zu verlassen, die richtig auf einige Nachrichten reagieren wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top