简体   繁体   中英

What's the quickest way to force an iOS app to crash?

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?

@throw NSInternalInconsistencyException;

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 :

  1. [][0]
  2. fatalError()

Objective-C :

  1. @[][0];
  2. 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

To force your program to crash with assert()

Swift lets you force an app crash using the assert() function. This takes two parameters: a condition to check, and a message to print if the assertion fails. Helpfully, any calls to assert() are ignored when your app is compiled in release mode (ie, for the App Store), which means these checks have no impact on your code's final performance.

Here are two examples of assert() being used:

assert(1 == 2, "Maths failure!")

To force a crash using fatalError()

Swift has a built-in function called fatalError() , which forces your application to crash. This might sound useful, but bear with me – this is an indispensable function for anyone serious about writing good Swift.

The fatalError( ) function has a special return type called Never, which Swift understands as meaning execution will never continue after this function has been called. As a result, you can use fatalError() in methods that return a value but you have nothing sensible to return.

Fortunately, fatalError() can fix that: if your typecast fails you can call fatalError() with a message explaining what happened, and if the typecast fails your app will terminat

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? MyCustomCell else {
        fatalError("Failed to load a MyCustomCell from the table.")
    }

    return cell
}
*(long*)0 = 0xDEADBEEF;

给出 EXC_BAD_ACCESS

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM