Was ist ein zuverlässiger Weg, um eine iOS-App zum Absturz zu bringen?

136

Ich möchte die Absturzberichte meiner App vor Ort testen, indem ich sie absichtlich abstürzen lasse, wenn der Benutzer eine bestimmte Aktion ausführt, die ein echter Benutzer wahrscheinlich nicht versehentlich ausführt.

Aber was ist eine gute und zuverlässige Methode, um die App zum Absturz zu bringen, die beim Kompilieren keine Warnung erzeugt?

Bearbeiten: Beachten Sie, dass viele scheinbar offensichtliche Antworten auf diese Frage zu Ausnahmen führen, die von Cocoa abgefangen werden und daher nicht zum Absturz der App führen.

Nestor
quelle
Ich komme WebKit discarded an uncaught exceptionfür all diese Ideen bisher! Wer wusste, dass es heutzutage so schwer ist, eine App zum Absturz zu bringen?
Nestor
Ich glaube, nichts davon hat etwas mit WebKit zu tun ...
BoltClock
23
Ja, öffnen Sie Safari auf einem iPad 1 und navigieren Sie zu einer Seite mit vielen Bildern. Funktioniert immer für mich. : /
Alan B
4
(void)0/0;,(void)*(char*)0;
Kevin
1
Seien Sie vorsichtig mit einigen der Antworten, die hier undefiniertes Verhalten hervorrufen . Das ist eigentlich ein sehr böser Rat!
Usr

Antworten:

140

Verwenden Sie in Objective-C C direkt, um einen schlechten Zugriff zu verursachen

strcpy(0, "bla");

Hinweis: Während dies auf jedem mir bekannten System funktioniert, führt dies in einer zukünftigen Version der C-Laufzeit ODER des Compilers möglicherweise nicht mehr zu einem Absturz. Siehe Ist die Nullzeiger-Dereferenzierung in Objective-C undefiniertes Verhalten? )

(In Kürze müssten Sie eine Brücke zu objC schlagen, um dies zu tun)

Daij-Djan
quelle
Dies ist meiner Meinung nach der zuverlässigste Weg
Michał Kreft
Ah ja, das umgeht auch das WebKit discarded an uncaught exceptionProblem.
Nestor
Es gab immer noch einen Tippfehler: D no @ "bla" aber "bla"
Daij-Djan
4
Anscheinend ( stackoverflow.com/questions/13651642/… ) ist dies ein undefiniertes Verhalten und tatsächlich eine sehr schlechte Antwort! Der Compiler kann beide Anweisungen legal optimieren und einfach nichts tun. Ich schlage vor, Sie löschen diese Antwort. Es könnte dazu führen, dass Menschen dies tatsächlich tun.
Usr
3
auf ios und osx und windows und redhat ist es immer abgestürzt, also würde ich im gegebenen kontext sagen, dass es gültig ist. Ich werde einen Haftungsausschluss hinzufügen
Daij-Djan
97

Mein aktueller Favorit:

assert(! "crashing on purpose to test <insert your reason here>");

Ein Klassiker:

kill( getpid(), SIGABRT );

Und einige pr0n:

*(long*)0 = 0xB16B00B5;

Alle von ihnen erzeugen Abstürze, die von meinem Absturzberichtstool erfasst wurden.

Djromero
quelle
14
assert stürzt bei Release-Versionen nicht ab, deshalb ist es ein assert
DarthMike
6
Dies hängt von Ihren Build-Einstellungen ab. Ich denke auch, dass es um das Testen geht. Es scheint in
Ordnung zu sein, Behauptungen
3
Viele Leute (einschließlich mir) hinterlassen Behauptungen in Release-Builds. Es gibt keinen Grund, sie zu deaktivieren.
Sulthan
5
@Sulthan: assert()ist eine Debug-Funktion, die wenig Sinn macht, solche Cruft in Release-Builds zu belassen. Dafür gibt es Unit-Tests.
MestreLion
18
IMHO assertist keine Debug-Funktion. Eine fehlgeschlagene Behauptung ist ein Fehler, den Sie für unmöglich gehalten haben. Es ist besser, einen Release-Build abzubrechen, als weiterhin ein Programm mit unvorhersehbaren Konsequenzen auszuführen.
Djromero
27

Da wir alle Clang für iOS verwenden, ist dies ziemlich zuverlässig:

__builtin_trap();

Dies hat den Vorteil, dass es genau für diesen Zweck entwickelt wurde, sodass keine Compiler-Warnungen oder -Fehler generiert werden sollten.

Dietrich Epp
quelle
22

Wie wäre es mit einem guten alten Stapelüberlauf :)

- (void)stackOverflow
{
    [self stackOverflow];
}
Taum
quelle
16

Am beliebtesten - nicht erkannter Selektorabsturz:

NSObject *object = [[NSObject alloc] init];
[object performSelector:@selector(asfd)];

Stellen Sie sicher, dass in dieser Klasse keine -asdf-Methode implementiert ist, haha

Oder Index jenseits der gebundenen Ausnahme:

NSArray * array = [NSArray array];
[array objectAtIndex:5];

Und natürlich kill( getpid(), SIGABRT );

wirrwarr
quelle
12

Ich denke, in Swift könnte man leicht einen fatalen Fehler machen:

func foo() {
    fatalError("crash!")
}

Es ist sogar beabsichtigt, diese Funktion zu verwenden, falls etwas schief geht, um die App zum Absturz zu bringen.

Um eine if-Anweisung in einem speziellen Fall zu vermeiden, können Sie auch verwenden precondition. Es ist ähnlich wie assert, macht also die Absicht (wenn gewünscht) ziemlich klar und ist nicht wie in der endgültigen Version entfernt assert. Es wird wie verwendet precondition(myBoolean, "This is a helpful error message for debugging.").

Borchero
quelle
9

Senden Sie eine Nachricht an ein freigegebenes Objekt

Andrey Chernukha
quelle
34
Das ist eigentlich sehr unzuverlässig. Sie können weiterhin Nachrichten an freigegebene Objekte senden, solange deren Speicher nicht wiederverwendet wird. Dies ist der ganze Grund, warum es in der Vergangenheit sehr schwierig war, Double-Release-Fehler zu debuggen. Nur wenn der Speicher von einem anderen Objekt zurückgefordert wird, kann das Senden einer Nachricht eine Ausnahme verursachen.
Mike Weller
7
exit(0);

(muss ... 30 Zeichen eingeben)

Steve Rogers
quelle
Vielen Dank für die positiven Stimmen, aber in der Tat wird die App dadurch beendet und kehrt zu Springboard zurück, was, obwohl es an sich nützlich sein kann, nicht das ist, was OP wollte, was eine nicht gefangene Ausnahme auslösen soll
Steve Rogers
6

Sie können auch eine Ausnahme auslösen:

[NSException raise:NSInternalInconsistencyException
            format:@"I want to test app crashes!."];
Alessandro Vendruscolo
quelle
2
Ich denke nicht, dass die Ausnahme so gut ist. Das Abfangen von Ausnahmen ist üblich, sodass Sie sie versehentlich abfangen können. Das Abfangen von Signalen ist nicht so häufig, so dass ein schlechter Zugriff oder ähnliche Dinge zuverlässiger wären. :)
Michał Kreft
3

Fügen Sie einer Ansicht, die ein Tippen mit 10 Fingern erkennt, eine Gestenerkennung hinzu (5 Finger für das iPhone, da 10 etwas überfüllt sein können). Dem GR ist eine Methode zugeordnet, die eine der zuvor genannten todsicheren Methoden ausführt, um Ihre App zum Absturz zu bringen. Die meisten Benutzer werden nicht 10 Finger auf Ihre App legen, sodass Sie vor dem allgemeinen Benutzer geschützt sind, der versehentlich den Absturz verursacht.

Sie sollten jedoch in der Lage sein, Testflight zu verwenden oder es einfach auf persönlichen Geräten bereitzustellen und in freier Wildbahn zu testen, bevor Sie es jemals an Apple senden. Ein erzwungener Absturz kann dazu führen, dass Ihre App von Apple abgelehnt wird.

jhelzer
quelle
Meine Cocos2d-App stürzt ab, wenn ich einen extremen Multi-Touch mache, und das ist ein ungelöster Fehler. Ich habe keine GR, aber ich habe Multitouch in Cocos2d aktiviert. Erlebe ich den von Ihnen beschriebenen Absturz? Sie meinen, dass dies erwartetes / gewünschtes Verhalten ist?
Fredrik Johansson
@Fredrik Ich glaube nicht, dass ein Absturz, den Sie beschreiben, erwartet wird (IMO-Abstürze sollten niemals erwartet werden, und ich persönlich halte es nicht für eine gute Idee, einen solchen Absturz absichtlich in Ihre App aufzunehmen). Sie können versuchen, den Absturz zu symbolisieren und herauszufinden, welche Methode den Absturz der App verursacht. Es könnte etwas innerhalb des Cocos2d-Frameworks sein, das den Absturz verursacht, wenn der "extreme Multi-Touch" auftritt. Wenn dies der Fall ist, ist es am besten, einen Fehler bei den Cocos2d-Leuten einzureichen.
Jhelzer
2

könnte so etwas versuchen

NSArray* crashingArray = [NSArray arrayWithCapacity:1];
[crashingArray release];

sollte auf einem EXC_BAD_ACCESS abstürzen (muss möglicherweise ein zweites Mal freigegeben werden, sollte aber normalerweise bereits so abstürzen)

Saliom
quelle
3
Kompiliert nicht mit aktiviertem ARC.
Vikingosegundo
Wenn Sie ARC verwenden, können Sie dies auch tun: NSArray * crashingArray = [NSArray arrayWithCapacity: 1]; [crashingArray objectAtIndex: 0]; Dies sollte abstürzen
Saliom
1

Ich werde gehen mit:int raise(int sig);

Um mehr Infos zu bekommen >man raise

Vytautas
quelle
0

Ich würde den Prozess einfach normal beenden:

kill(getpid(), SIGKILL);

Wenn Sie also einen Handler mit Signal installieren, können Sie auch den Absturz behandeln und das Schreiben geöffneter Dateien und dieser Dinge beenden.

Ramy Al Zuhouri
quelle
Dies ist bereits in Madmws Antwort enthalten
vikingosegundo
0

ich benutze

[self doesNotRecognizeSelector:_cmd]; 
Duyen-Hoa
quelle
2
Dieser Beitrag wird automatisch als minderwertig gekennzeichnet, da es sich nur um Code handelt. Würde es Ihnen etwas ausmachen, es durch Hinzufügen von Text zu erweitern, um zu erklären, warum dies das Problem löst?
Gung - Reinstate Monica
0

Bei der Arbeit mit RubyMotion verwende ich Folgendes:

    n=Pointer.new ('c', 1)
    n[1000] ='h'
Raymond
quelle
0

Versuche dies:

- (IBAction)Button:(id)sender
{
    NSArray *array = [NSArray new];
    NSLog(@"%@",[array objectAtIndex:8]);
}
Rajesh Loganathan
quelle
-1

eine falsche NSLogAussage wird es tun

NSLog(@"%@",1);
Mutawe
quelle