J'essaie de tester mes analyses de plantage. Je ne savais pas à quel point il était difficile de faire planter une application à volonté. cela semble si simple en milieu de programmation. Quelqu'un a-t-il une suggestion sur la façon de forcer mon application à se bloquer? Et je ne veux pas dire un petit crash "erreur de mémoire", je veux dire que le téléphone ne sait pas quoi faire avec lui-même. J'en ai besoin pour au moins entrer dans les journaux de l'appareil comme un crash, dans l'organisateur de Xcode. Aucune suggestion?
@throw NSInternalInconsistencyException;
Tant de façons de tuer une application! Voici deux doublures:
[self performSelector:@selector(die_die)];
aussi
@[][666];
Écrivez simplement assert(NO)
. Cela vérifie la condition donnée en paramètre et plante l'application si elle est fausse.
Modifier:
exit(0)
fera aussi l'affaire
int* p = 0;
*p = 0;
Donne une EXC_BAD_ACCESS (code=2, address=0x0)
Modifier:
Après que Greg Parkers ait commenté qu'un compilateur est autorisé à optimiser les déclarations ci-dessus, cela m'a fait réfléchir davantage sur les déclarations ci-dessus, et pourquoi Greg Parker a raison:
En fait, déréférencer le pointeur NULL est un "comportement indéfini" en C et C++ (voir aussi C99 §6.5.3.2/4).
Cela signifie que l'effet des instructions ci-dessus dépend du compilateur. Ce "comportement indéfini" signifie également que le compilateur est autorisé à appliquer quelques optimisations, ce qui peut avoir pour effet que les instructions ci-dessus seront "toujours optimisées" - comme l'affirme Greg Parker.
Eh bien, maintenant cela m'a rendu curieux de savoir ce que le clang ferait réellement:
Voici le petit programme de test:
int main(int argc, const char * argv[])
{
int* p = 0;
*p = 0;
return 0;
}
avec l'optimisation réglée sur "-Ofast", nous obtenons ce démontage:
0x100000f90: pushq %rbp
0x100000f91: movq %rsp, %rbp
0x100000f94: ud2
où ud2
est un opcode signifiant "opcode non défini" et provoque une exception CPU:
`EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)`
(Peut-être que @GregParker peut expliquer pourquoi clang choisit cette approche?)
Bien que cela soit intéressant, il fait uniquement référence au "déréférencement du pointeur NULL". Si nous avons ceci à la place:
int* p = (int*)1;
*p = 0;
le programme se bloque comme prévu - mais nécessite la "condition préalable" que le matériel refuse d'écrire sur cette adresse (non valide).
Je pense que le bon ancien index de tableau hors de portée est une garantie de "crash réussi", alors voici ma liste préférée:
Swift 4 :
[][0]
fatalError()
Objectif-C :
@[][0];
int *x = nil; *x = 0;
Bien que @throw NSInternalInconsistencyException;
Corrige votre problème, c'est une exception (pas un plantage), donc peut être intercepté .
Je trouve souvent utile que l'application démarre, fasse son travail un peu, puis plante après 10 secondes. Dans ce cas (pour Objective-C), j'utilise:
[self performSelector:NSSelectorFromString(@"crashme:") withObject:nil afterDelay:10];
Un avantage secondaire à cela est que le compilateur ne lance aucun avertissement (si vous utilisez Objective-C) lorsque le sélecteur n'est pas trouvé. :)
Swift:
self.perform("crashme:", with: nil, afterDelay: 10)
Une manière plus contrôlée serait de lancer une exception vous-même:
@throw [NSException exceptionWithName:NSGenericException reason:@"" userInfo:nil];
Vérifier NSException.h
pour plus d'exceptions.
Pour Swift ceux-ci ont fonctionné pour moi:
assert(false, "sdf")
Et ça:
var hey:[Int] = []
hey[0] = 1