Jaki jest niezawodny sposób na awarię aplikacji na iOS?

136

Chcę przetestować raportowanie awarii mojej aplikacji w terenie, celowo powodując awarię, gdy użytkownik wykonuje określoną czynność, której rzeczywisty użytkownik prawdopodobnie nie wykona przypadkowo.

Ale jaki jest dobry niezawodny sposób na spowodowanie awarii aplikacji, która nie generuje ostrzeżenia w czasie kompilacji?

Edycja: Zwróć uwagę, że wiele pozornie oczywistych odpowiedzi na to pytanie powoduje wyjątki, które zostają przechwycone przez Cocoa, a tym samym nie powodują awarii aplikacji.

Nestor
źródło
Na razie dostaję WebKit discarded an uncaught exceptionza wszystkie te pomysły! Kto by pomyślał, że ostatnio tak trudno było spowodować awarię aplikacji?
Nestor
Nie sądzę, żeby to miało coś wspólnego z
WebKitem
23
Tak, otwórz Safari na iPadzie 1 i przejdź do strony z dużą ilością obrazów. Zawsze mi pasuje. : /
Alan B
4
(void)0/0;,(void)*(char*)0;
Kevin
1
Uważaj na niektóre odpowiedzi, które wywołują niezdefiniowane zachowanie . To naprawdę bardzo nieprzyjemna rada!
usr

Odpowiedzi:

140

w Objective-C użyj C bezpośrednio, aby spowodować zły dostęp

strcpy(0, "bla");

Uwaga: chociaż działa to na każdym systemie, który znam - w przyszłej wersji środowiska wykonawczego C LUB kompilatora może to już nie prowadzić do awarii. zobacz Is null pointer dereference undefined Behavior in Objective-C? )

(w szybkim tempie musiałbyś połączyć się mostem z objC, aby to zrobić)

Daij-Djan
źródło
to IMHO najbardziej niezawodny sposób
Michał Kreft
Ach tak, to też WebKit discarded an uncaught exceptionrozwiązuje problem.
Nestor
wciąż była literówka: D no @ "bla" ale "bla"
Daij-Djan.
4
Najwyraźniej ( stackoverflow.com/questions/13651642/… ) jest to niezdefiniowane zachowanie i właściwie bardzo zła odpowiedź! Kompilator może legalnie zoptymalizować obie instrukcje i po prostu nic nie robić. Proponuję usunąć tę odpowiedź. Może to skłonić ludzi do tego.
usr
3
na iOS, OSX i Windows i ponownie, że zawsze się zawieszał, więc w danym kontekście powiedziałbym, że jest poprawny. Dodam wyłączenie odpowiedzialności
Daij-Djan
97

Mój obecny ulubiony:

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

Klasyk:

kill( getpid(), SIGABRT );

I trochę pr0n:

*(long*)0 = 0xB16B00B5;

Wszystkie z nich generują awarie przechwycone przez moje narzędzie do raportowania awarii.

djromero
źródło
14
assert nie zawiesza się w wersjach wydanych, dlatego jest to
asercja
6
zależy to od ustawień kompilacji; również myślę, że pytanie dotyczy testowania, wydaje się w porządku, aby zachować potwierdzenia w kompilacjach testowych
djromero,
3
Wiele osób (w tym ja) zostawia potwierdzenia w kompilacjach wydań. Nie ma powodu, aby je wyłączać.
Sulthan
5
@Sulthan: assert()to funkcja debugowania, nie ma sensu zostawiać takich okrucieństw w kompilacjach wydań. Istnieją na to testy jednostkowe.
MestreLion
18
IMHO assertnie jest funkcją debugowania. Nieudana asercja to błąd, który uważałeś za niemożliwy. Lepiej przerwać, nawet kompilację wydania, niż kontynuować uruchamianie programu z nieprzewidywalnymi konsekwencjami.
djromero
27

Ponieważ wszyscy używamy Clang na iOS, jest to dość niezawodne:

__builtin_trap();

Ma to tę zaletę, że został zaprojektowany dokładnie w tym celu, więc nie powinien generować żadnych ostrzeżeń ani błędów kompilatora.

Dietrich Epp
źródło
22

Co powiesz na stare dobre przepełnienie stosu :)

- (void)stackOverflow
{
    [self stackOverflow];
}
Taum
źródło
16

Najpopularniejszy - nierozpoznana awaria selektora:

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

Upewnij się, że nie masz metody -asdf zaimplementowanej w tej klasie haha

Lub indeks poza ograniczonym wyjątkiem:

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

I oczywiście kill( getpid(), SIGABRT );

wirrwarr
źródło
12

Myślę, że w Swift można łatwo rzucić fatalny błąd:

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

W rzeczywistości jest nawet przeznaczone do użycia tej funkcji na wypadek, gdyby coś poszło nie tak, aby spowodować awarię aplikacji.

Aby uniknąć instrukcji if w szczególnym przypadku, możesz również użyć precondition. Jest podobny do assert, sprawia, że ​​zamiar (jeśli jest potrzebny) jest dość jasny i nie jest usuwany w ostatecznej wersji jako assert. Jest używany jak precondition(myBoolean, "This is a helpful error message for debugging.").

borchero
źródło
9

Wyślij wiadomość do zwolnionego obiektu

Andrey Chernukha
źródło
34
W rzeczywistości jest to bardzo zawodne. Nadal możesz wysyłać wiadomości do zwolnionych obiektów, o ile ich pamięć nie zostanie ponownie wykorzystana. To jest cały powód, dla którego ludzie mieli historycznie bardzo trudne debugowanie błędów podwójnego wydania. Dopiero gdy pamięć jest odzyskiwana przez inny obiekt, wysłanie wiadomości może spowodować wyjątek.
Mike Weller
7
exit(0);

(należy ... wpisać ... 30 znaków)

Steve Rogers
źródło
Dzięki za upvotes ale w rzeczywistości to uczynią aplikacja zakończyć i powrócić do Springboard, która, choć może on być przydatny w sobie, nie jest to, co chciała PO, która ma wyzwalać untrapped wyjątek
Steve Rogers
6

Możesz również zgłosić wyjątek:

[NSException raise:NSInternalInconsistencyException
            format:@"I want to test app crashes!."];
Alessandro Vendruscolo
źródło
2
Nie sądzę, żeby wyjątek był taki dobry, wychwytywanie wyjątku jest powszechne, więc można go przypadkowo złapać. Wyłapywanie sygnałów nie jest tak powszechne, więc zły dostęp lub podobne rzeczy byłyby bardziej niezawodne. :)
Michał Kreft
3

Dodaj rozpoznawanie gestów do widoku, który rozpoznaje stuknięcie 10 palcami (5 palców w przypadku iPhone'a 10 może być trochę zatłoczonych). GR ma dołączoną metodę, która wykonuje każdy z wcześniej wspomnianych niezawodnych sposobów spowodowania awarii aplikacji. Większość użytkowników nie położy 10 palców na twojej aplikacji, więc jesteś bezpieczny przed przypadkowym spowodowaniem awarii przez ogólnego użytkownika.

Jednak powinieneś być w stanie użyć czegoś takiego jak Testflight lub po prostu wdrożyć go na urządzeniach osobistych i przetestować na wolności, zanim prześlesz go do Apple. Wymuszona awaria może spowodować odrzucenie aplikacji przez Apple.

jhelzer
źródło
Moja aplikacja Cocos2d ulega awarii, gdy wykonuję ekstremalny multi-touch, i mam to jako nierozwiązany błąd. Nie mam żadnego GR, ale włączyłem multitouch w Cocos2d. Czy doświadczam awarii, którą opisujesz? Masz na myśli, że jest to oczekiwane / pożądane zachowanie?
Fredrik Johansson
@Fredrik Nie sądzę, abyś się spodziewał awarii, którą opisujesz (awarie IMO nigdy nie powinny się spodziewać i osobiście nie uważam, aby celowo umieszczać ją w swojej aplikacji w tym celu). Możesz spróbować symbolizować awarię i dowiedzieć się, jaka metoda powoduje awarię aplikacji. Może to być coś wewnątrz struktury Cocos2d, które powoduje awarię, gdy wystąpi „ekstremalny multi-touch”. Jeśli tak jest, najlepszym rozwiązaniem jest zgłoszenie błędu z chłopakami z Cocos2d.
jhelzer
2

mógłby spróbować czegoś takiego

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

powinien się zawiesić na EXC_BAD_ACCESS (może wymagać zwolnienia go po raz drugi, ale normalnie powinien już się zawiesić)

Saliom
źródło
3
Nie można skompilować z włączonym ARC.
vikingosegundo
cóż, jeśli używasz ARC, możesz również zrobić to: NSArray * crashingArray = [NSArray arrayWithCapacity: 1]; [crashingArray objectAtIndex: 0]; to powinno się
zawiesić
1

Pójdę z:int raise(int sig);

Aby uzyskać więcej informacji >man raise

Vytautas
źródło
0

Po prostu zabiłbym ten proces normalnie:

kill(getpid(), SIGKILL);

Więc jeśli zainstalujesz program obsługi z sygnałem, możesz również obsłużyć awarię, kończąc zapisywanie otwartych plików i innych rzeczy.

Ramy Al Zuhouri
źródło
jest to już zawarte w odpowiedzi
madmw
0

używam

[self doesNotRecognizeSelector:_cmd]; 
Duyen-Hoa
źródło
2
Ten post jest automatycznie oznaczany jako niskiej jakości, ponieważ zawiera tylko kod. Czy mógłbyś go rozszerzyć, dodając tekst wyjaśniający, dlaczego to rozwiązuje problem?
gung - Przywróć Monikę
0

Podczas pracy z RubyMotion używam tego:

    n=Pointer.new ('c', 1)
    n[1000] ='h'
Raymond
źródło
0

Spróbuj tego:

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

błędne NSLogstwierdzenie to zrobi

NSLog(@"%@",1);
Mutawe
źródło