Quel est le moyen fiable de faire planter une application iOS?

136

Je souhaite tester le rapport de plantage de mon application sur le terrain en le faisant délibérément planter lorsque l'utilisateur effectue une action particulière qu'un utilisateur réel est peu susceptible de faire accidentellement.

Mais quel est un bon moyen fiable de faire planter l'application sans créer d'avertissement au moment de la compilation?

Edit: Notez que de nombreuses réponses apparemment évidentes à cette question entraînent des exceptions qui sont interceptées par Cocoa et n'entraînent donc pas le plantage de l'application.

Nestor
la source
Je reçois WebKit discarded an uncaught exceptiontoutes ces idées jusqu'à présent! Qui savait qu'il était si difficile de faire planter une application ces jours-ci?
Nestor
Je ne pense pas que tout cela ait quelque chose à voir avec WebKit ...
BoltClock
23
Ouais, ouvrez Safari sur un iPad 1 et accédez à une page avec beaucoup d'images. Fonctionne toujours pour moi. : /
Alan B
4
(void)0/0;,(void)*(char*)0;
Kevin
1
Soyez prudent avec certaines des réponses ici invoquant un comportement non défini . C'est en fait un très mauvais conseil!
usr

Réponses:

140

en Objective-C, utilisez C directement pour provoquer un mauvais accès

strcpy(0, "bla");

Remarque: bien que cela fonctionne sur n'importe quel système que je connais - dans une future version du runtime C OU du compilateur, cela pourrait ne plus conduire à un crash. voir Le comportement de déréférence de pointeur nul est-il indéfini dans Objective-C? )

(en un rien de temps, vous devrez passer à objC pour ce faire)

Daij-Djan
la source
c'est à
mon humble avis le
Ah oui, cela contourne le WebKit discarded an uncaught exceptionproblème aussi.
Nestor
il y avait encore une faute de frappe: D no @ "bla" mais "bla"
Daij-Djan
4
Apparemment ( stackoverflow.com/questions/13651642/… ), c'est un comportement indéfini et en fait une très mauvaise réponse! Le compilateur peut légalement optimiser les deux instructions et ne rien faire. Je vous suggère de supprimer cette réponse. Cela pourrait amener les gens à faire cela.
usr
3
sur ios et osx et windows et redhat il s'est toujours écrasé donc dans le contexte donné, je dirais que c'est valide. Je vais ajouter une clause de non
Daij-Djan
97

Mon coup de coeur actuel:

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

Un classique:

kill( getpid(), SIGABRT );

Et certains pr0n:

*(long*)0 = 0xB16B00B5;

Tous génèrent des plantages capturés par mon outil de rapport de crash.

Djromero
la source
14
assert ne
plante
6
cela dépend de vos paramètres de construction; aussi, je pense que la question concerne les tests, il semble correct de conserver les
affirmations
3
Beaucoup de gens (moi y compris) laissent des affirmations dans les versions de version. Il n'y a aucune raison de les désactiver.
Sulthan
5
@Sulthan: assert()est une fonctionnalité de débogage, cela n'a pas de sens de laisser une telle cruauté dans les versions de version. Il existe des tests unitaires pour cela.
MestreLion
18
IMHO assertn'est pas une fonctionnalité de débogage. Une affirmation ratée est un bug que vous pensiez impossible. Il vaut mieux abandonner, même une version de version, que de continuer à exécuter un programme avec des conséquences imprévisibles.
djromero
27

Puisque nous utilisons tous Clang pour iOS, c'est assez fiable:

__builtin_trap();

Cela présente l'avantage d'être conçu exactement dans ce but, il ne devrait donc pas générer d'avertissements ou d'erreurs du compilateur.

Dietrich Epp
la source
22

Que diriez-vous d'un bon vieux débordement de pile :)

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

Le plus populaire - plantage du sélecteur non reconnu:

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

Assurez-vous que la méthode -asdf n'est pas implémentée dans cette classe haha

Ou index au-delà de l'exception liée:

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

Et bien sûr kill( getpid(), SIGABRT );

Wirrwarr
la source
12

Je pense que dans Swift, vous pouvez facilement lancer une erreur fatale:

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

Il est même prévu d'utiliser cette fonctionnalité en cas de problème pour faire planter l'application.

Pour éviter une instruction if dans un cas particulier, vous pouvez également utiliser precondition. Il est similaire à assert, rend donc l'intention (si vous le souhaitez) assez claire et n'est pas supprimé dans la version finale en tant que assert. Il est utilisé comme precondition(myBoolean, "This is a helpful error message for debugging.").

borchero
la source
9

Envoyer un message à un objet désalloué

Andrey Chernukha
la source
34
C'est en fait très peu fiable. Vous pouvez toujours envoyer des messages aux objets désalloués tant que leur mémoire n'est pas réutilisée. C'est la raison pour laquelle les gens ont toujours eu du mal à déboguer les erreurs de double version. Ce n'est que lorsque la mémoire est récupérée par un autre objet que l'envoi d'un message peut provoquer une exception.
Mike Weller
7
exit(0);

(doit ... taper ... 30 caractères)

Steve Rogers
la source
Merci pour les votes positifs, mais en fait, cela obligera l'application à se terminer et à revenir à Springboard, ce qui, bien que cela puisse être utile en soi, n'est pas ce que OP voulait, qui est de déclencher une exception non piégée
Steve Rogers
6

Vous pouvez également lever une exception:

[NSException raise:NSInternalInconsistencyException
            format:@"I want to test app crashes!."];
Alessandro Vendruscolo
la source
2
Je ne pense pas que l'exception soit ce bon moyen, la capture d'exception est courante, vous pourriez donc l'attraper accidentellement. Attraper des signaux n'est pas si courant, donc un mauvais accès ou des choses similaires seraient plus fiables. :)
Michał Kreft
3

Ajoutez un outil de reconnaissance de gestes à une vue qui reconnaît une pression de 10 doigts (5 doigts pour iPhone comme 10 peuvent être un peu encombrés). Le GR a une méthode qui lui est attachée qui exécute n'importe lequel des moyens infaillibles mentionnés précédemment pour faire planter votre application. La plupart des utilisateurs ne vont pas poser 10 doigts sur votre application, vous êtes donc à l'abri de l'utilisateur général qui provoque accidentellement le crash.

Cependant, vous devriez pouvoir utiliser quelque chose comme Testflight ou simplement le déployer sur des appareils personnels et le tester dans la nature avant de le soumettre à Apple. Un crash forcé pourrait entraîner le rejet de votre application par Apple.

jhelzer
la source
Mon application Cocos2d se bloque lorsque je fais un multi-touch extrême, et j'ai cela comme un bogue non résolu. Je n'ai pas de GR, mais j'ai activé le multitouch dans Cocos2d. Est-ce que je rencontre le crash que vous décrivez? Vous voulez dire que c'est un comportement attendu / voulu?
Fredrik Johansson
@Fredrik Je ne pense pas que le crash que vous décrivez soit attendu (les plantages de l'OMI ne devraient jamais être attendus et je ne pense personnellement pas que ce soit une bonne idée d'en mettre un dans votre application). Vous pouvez essayer de symboliser le plantage et de découvrir exactement quelle méthode provoque le plantage de l'application. Cela pourrait être quelque chose à l'intérieur du framework Cocos2d qui provoque le crash lorsque le «multi-touch extrême» se produit. Si tel est le cas, votre meilleur pari est de déposer un bug avec les gars de Cocos2d.
jhelzer
2

pourrait essayer quelque chose comme

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

devrait planter sur un EXC_BAD_ACCESS (il pourrait être nécessaire de le relâcher une deuxième fois mais normalement il devrait déjà planter comme ça)

Saliom
la source
3
Ne compilera pas avec ARC activé.
vikingosegundo
eh bien, si vous utilisez ARC, vous pouvez également faire ceci: NSArray * crashingArray = [NSArray arrayWithCapacity: 1]; [crashingArray objectAtIndex: 0]; cela devrait
planter
1

J'irai avec:int raise(int sig);

Pour en savoir plus >man raise

Vytautas
la source
0

Je tuerais simplement le processus normalement:

kill(getpid(), SIGKILL);

Donc, si vous installez un gestionnaire avec signal, vous pouvez également gérer le plantage, en finissant d'écrire les fichiers ouverts et ces choses.

Ramy Al Zuhouri
la source
cela est déjà inclus dans la réponse de
madmw
0

j'utilise

[self doesNotRecognizeSelector:_cmd]; 
Duyen-Hoa
la source
2
Ce message est automatiquement signalé comme étant de mauvaise qualité car il ne s'agit que de code. Pourriez-vous l'élargir en ajoutant du texte pour expliquer pourquoi cela résout le problème?
gung - Réintègre Monica le
0

Lorsque je travaille avec RubyMotion, j'utilise ceci:

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

Essaye ça:

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

une fausse NSLogdéclaration le fera

NSLog(@"%@",1);
Mutawe
la source