@throw NSInternalInconsistencyException;
What's the quickest way to force an iOS app to crash?
-
06-10-2022 - |
Вопрос
I'm trying to test my crash analytics. I didn't realize how hard it is to make an app crash at will. it seems so simple mid-programming. Does anybody have a suggestion as to how i'd force my app to crash? And i don't mean a little "memory error" crash, i mean the phone doesn't know what to do with itself. I need it to at the very least enter into the device logs as a crash, in Xcode's organizer. Any suggestions?
Решение
Другие советы
So many ways to kill an app! Here are two one liners:
[self performSelector:@selector(die_die)];
also
@[][666];
Just write assert(NO)
. This checks the condition given as parameter and crashes the app if it is false.
Edit:
exit(0)
will also do the trick
int* p = 0;
*p = 0;
Gives a EXC_BAD_ACCESS (code=2, address=0x0)
Edit:
After Greg Parkers comment that a compiler is allowed to optimize away the above statements, it made me think more thoroughly about the above statements, and why Greg Parker is right:
In fact, dereferencing the NULL pointer is "undefined behavior" in C and C++ (see also C99 §6.5.3.2/4).
This means, the effect of the above statements depend on the compiler. This "undefined behavior" also means, that the compiler is allowed to apply a couple of optimizations, which may have the effect that the above statements will be "optimized aways" - as Greg Parker asserts.
Well, now that made me curious what clang would actually do:
This is the small test program:
int main(int argc, const char * argv[])
{
int* p = 0;
*p = 0;
return 0;
}
with optimization set to "-Ofast", we get this disassembly:
0x100000f90: pushq %rbp
0x100000f91: movq %rsp, %rbp
0x100000f94: ud2
where ud2
is an opcode meaning "undefined opcode" and causes a CPU exception:
`EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)`
(Maybe @GregParker can comment why clang chooses this approach?)
While this is interesting, it refers to "dereferencing the NULL pointer" only. If we have this instead:
int* p = (int*)1;
*p = 0;
the program crashes as expected - but requires the "prerequisite" that the hardware refuses writes to this (invalid) address.
I think the good old array index out of range is a guarantee of "successful crash", so here my favourite list:
Swift 4:
[][0]
fatalError()
Objective-C:
@[][0];
int *x = nil; *x = 0;
Although @throw NSInternalInconsistencyException;
fixes your problem, is an exception (not a crash), hence might be caught.
I often find it useful to have the application start up, do its thing for a bit, and then crash after 10 seconds. In this case (for Objective-C), I use:
[self performSelector:NSSelectorFromString(@"crashme:") withObject:nil afterDelay:10];
A secondary benefit to this is that the compiler doesn't throw any warnings (if using Objective-C) about the selector not being found. :)
Swift:
self.perform("crashme:", with: nil, afterDelay: 10)
A more controlled way would be to actually throw an exception yourself:
@throw [NSException exceptionWithName:NSGenericException reason:@"" userInfo:nil];
Check NSException.h
for more exceptions.
For swift these worked for me:
assert(false, "sdf")
And this:
var hey:[Int] = []
hey[0] = 1
*(long*)0 = 0xDEADBEEF;
Gives an EXC_BAD_ACCESS