What's a reliable way to make an iOS app crash? - iphone

I want to test my app's crash reporting out in the field by deliberately having it crash when the user performs a particular action that a real user is unlikely to do accidentally.
But what's a good reliable way of making the app crash that doesn't create a warning at compile time?
Edit: Note that many seemingly obvious answers to this question result in exceptions that get caught by Cocoa and thus don't result in the app crashing.

in Objective-C use C directly to cause a bad access
strcpy(0, "bla");
Note: while this works on any system I know -- in a future version of the C runtime OR the compiler this might not lead to a crash anymore. see Is null pointer dereference undefined behavior in Objective-C?)
(in swift you would have to bridge to objC to do this)

My current favourite:
assert(! "crashing on purpose to test <insert your reason here>");
A classic:
kill( getpid(), SIGABRT );
And some pr0n:
*(long*)0 = 0xB16B00B5;
All of them generate crashes captured by my crash reporting tool.

Since we all use Clang for iOS, this is fairly reliable:
__builtin_trap();
This has the benefit that it's designed for exactly this purpose, so it shouldn't generate any compiler warnings or errors.

How about a good old stack overflow :)
- (void)stackOverflow
{
[self stackOverflow];
}

abort(); causes abnormal termination… That is a crash.

Most popular one - unrecognised selector crash:
NSObject *object = [[NSObject alloc] init];
[object performSelector:#selector(asfd)];
Make sure you don't have -asdf method implemented in that class haha
Or index beyond bound exception:
NSArray * array = [NSArray array];
[array objectAtIndex:5];
And of course
kill( getpid(), SIGABRT );

I think in Swift you could easily throw a fatal error:
func foo() {
fatalError("crash!")
}
It is actually even intended to use this feature in case something goes wrong in order to make the app crash.
To avoid an if statement in a special case, you could use precondition, too. It's similar to assert, makes thus the intention (if wanted) pretty clear and is not removed in the final release as assert. It is used like precondition(myBoolean, "This is a helpful error message for debugging.").

Send a message to a deallocated object

exit(0);
(must... type... 30 characters)

You can also raise an exception:
[NSException raise:NSInternalInconsistencyException
format:#"I want to test app crashes!."];

Add a gesture recognizer to a view that recognizes a 10 finger tap (5 fingers for iPhone as 10 can get a bit crowded). The GR has a method attached to it that executes anyone of the previously mentioned surefire ways to get your app to crash. Most users are not going to lay 10 fingers down on your app, so you're safe from the general user accidentally causing the crash.
However you should be able to use something like Testflight or just deploying it to personal devices and test in the wild before ever submitting it to Apple. Having a forced crash could get your app rejected by Apple.

could try something like
NSArray* crashingArray = [NSArray arrayWithCapacity:1];
[crashingArray release];
should crash on an EXC_BAD_ACCESS (might need to release it a second time but normaly it should crash like this already)

I will go with:int raise(int sig);
To get more info >man raise

I would just kill the process normally:
kill(getpid(), SIGKILL);
So if you install a handler with signal you can also handle the crash, finishing to write opened files and these things.

I use
[self doesNotRecognizeSelector:_cmd];

When working with RubyMotion I use this:
n=Pointer.new ('c', 1)
n[1000] ='h'

Try this:
- (IBAction)Button:(id)sender
{
NSArray *array = [NSArray new];
NSLog(#"%#",[array objectAtIndex:8]);
}

a wrong NSLog statement will do it
NSLog(#"%#",1);

Related

Thread 1: EXC_BAD_ACCESS (code=1, address=0xf00000c)

I have problem with Thread 1: EXC_BAD_ACCESS (code=1, address=0xf00000c) and I don't know how to resolve it.
It appeared when I change some object in core date and save it and I try to pop this controller to parent.
This error is in main() with retVal.
here is some code
int retVal;
#try {
retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
*/\ error is here**
}
#catch (NSException *exception) {
NSLog(#"%#", [exception callStackSymbols]);
#throw exception;
}
return retVal;
After re-runing app all my changes are in core data. What is more this problem is only on iOS 7. iOS 6.1 is ok.
Does someone have idea how to resolve it?
As a comment said this error is likely to be deep in your code. If the culprit is a zombie, the easiest way to find it is to run it (preferably in the latest Xcode, currently Xcode 5, as it has been improved) in profiler and choose "Zombies". When it fails, you can see the history of everything that has happened to the object.
Also, set an exception breakpoint. You may get a break when the error happens instead of in main, where the exception gets passed up.
I just had the exact same problem.
Looked here and found nothing so I started backtracking until I thought, maybe I should try Clean Build Folder🤔
I was glad it was as easy as CLEAN BUILD FOLDER!!!
Product- Clean Build Folder(⇧ ⌘ K)
😀
I resolved this problem with "Zombies" and the problem was with
[UIScrollView(UIScrollViewInternal) _notifyDidScroll]
I added
- (void)dealloc {
self.tableView.delegate = nil;
}
This problem was only in iOS 7.
Thanks for help!
I have resolve this issue only by debugging the source code and re-analyze my logic.
Below are some reference that help me lot.
EXC_BAD_ACCESS means that message was sent to a point in the memory where there’s no instance of a class to execute it. Thus “bad access”.
You will get EXC_BAD_ACCESS in 3 cases:
An object is not initialized
An object is already released
Something else that is not very likely to happen
That’s already a good starting point. Start using the debugger, if you recently added a new object to the class you’re working on, put a breakpoint at the line before the freshly added object is used for the first time and check the values in the debugger.
What’s happening most though is that you will be sending a message to an overreleased object – i.e. object that is gone from the call stack. In this cases everything (and indeed everything) you will get in the console will be just :EXC_BAD_ACCESS
This is because the object is gone, there is no information what class was it, or what source file or anything else.
Please try to avoid using zombies for this.
EXC_BAD_ACCESS means there is no instance of a class to execute it.
There are 2 or more possibilities:
An object is not initialized
An object is already released
Please debug application carefully and analyze each object carefully. That might solve your issue.
I solved the same problem by finding out that the name of one of my NSString variables had the same name as one of the frameworks' class variables. Took seconds to change the name a little and problem disappeared.
With such a huge number of class variables in frameworks, it is very likely that once in a while, every programmer just by coincidence names some variable in his class exactly the same as one used somewhere in framework classes.
So it doesn't have to be Xcode bug in most cases.
In my case, I was using third-party library and I forgot to set custom-class name in Storyboard Identity Inspector
And there may be another issue which I faced today:
I had a mutable dictionary with a non-object entry try. There was a code snippet with adding a BOOL value to the dictionary. So no wonder that I got this error =).
In my case it was trying to log an Int32 with %s in print statement
in my view this is the equivalent of every other language NullPointerException,
but unlike other languages there are no hellping pointers (class name / method or line of the occurrence / god forbid a Stacktrace),
so the only thing i could do to solve it fast is to start printing main functions and views, (a very primitive solution),
create a swift: Debug.swift
add this function into Debug.swift:
public func trace(_ message: String = "", file: String = #file, function: String = #function, line: Int = #line)
{
print("**** \(file).\(function)[\(line)]: \(message)")
}
then you can use it like this:
trace("initializing")
to use it inside a var do this:
let _ = trace("initializing")
this should print something similar to this:
**** /path/to/my/file/MyFile.swift.someFunc()[18]: initializing
this is how i started adding debug lines to gain some flow record, so next time i have a EXC_BAD_ACCESS i will have a clue where the problem leis
don't forget to disable the prints during production deployment

memory leak from method in analyzer

Im nearing the end of my first app and im trying to go through my errors and memory management and clean everything up.
In the analyzer in xcode the following line comes up as a "potential memory leak"
- (NSMutableArray *) convertStringToASCIIMutableArray:(NSString *)stringIn {
NSLog(#"call:convertStringToASCIIMutableArray");
NSMutableArray *arrayOut = [[NSMutableArray alloc] initWithCapacity:stringIn.length];
//NSMutableArray *arrayOut = [NSMutableArray arrayWithCapacity:stringIn.length];
for (int i=0; i<stringIn.length; i++) {
unichar ch = [stringIn characterAtIndex:i];
if (ch > 96 && ch<123) ch = ch - 32; // convert to all capitals
[arrayOut insertObject:[NSNumber numberWithChar:ch] atIndex:i];
}
return arrayOut;
}
But when i remove the alloc call (as in the commented line or with an autorelease) the app crashes. Anyone know whats going on here?
"arrayOut" isn't autoreleased if you are in a manual reference counting environment.
Change return arrayOut to return [arrayOut autorelease] and the array will be released at the end of the current runloop.
Not seeing anything here. The "potential leak" is there because you're creating the mutable array using alloc-init and not releasing it when the method completes. Since you are returning the object, I recommend you create an autorelease version.
Now for the app crashing when using an autorelease version, you'll have to look at where it is crashing and what you're doing leading up to the crash. Do you know about setting up a breakpoint when an exception is raised? If not, follow this and the code will stop at the line when the crash happens so you can debug it:
Press Command+6 in xcode
Click on the + button in lower left corner
Select Add exception breakpoint
Set options for All exceptions, on throw and hit Done.
Well I didnt really solve my problem per se, but I converted my project to compile with the new Automatic Reference Counting (ARC, thanks #Kurt Revis and #Byron for bringing this feature to my attention)
To convert my project I just went to edit>Refactor>Convert to Obj-C ARC. Then I had to conform to the new rules of memory management as prompted after doing the "check" presented in the refactoring window. Essentially I had to remove some releases in my dealloc method, but it came up with some alerts in the issue navigator to tell me what to do.
ARC seems to be great. More info available here:
Steffen Itterheim

try catch final is not catching exception

While on return to my app from getting phone number from address book, if by mistake i fetch some address or any thing except for phone number, the code in the try catch final gives the following but doesn't catch it, any idea is appreciated in advance:
*** -[CFDictionary length]: message sent to deallocated instance 0x6a4db70
Code:
strContact = (NSString *)phone; CFRelease(phone);
// NSLog(#"%#", strContact);
CFRelease(multi);
name = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSRegularExpression *regex = [[[NSRegularExpression alloc] initWithPattern:#"[a-zA-Z]" options:0 error:NULL] autorelease];
// Assuming you have some NSString myString.
NSUInteger matches = [regex numberOfMatchesInString:strContact options:0 range:NSMakeRange(0, [strContact length])];
OK, I think I understand your question now. It just took me a while.
So, I'm assuming you have Zombie Objects enabled (NSZombieEnabled) and you're wondering why you can't catch this error --sending a message to a zombie-- with a #try/#catch structure.
The short answer is NSZombies don't throw an Objective-C exception (one that you can catch this way). There wouldn't really be a point to that, since you wouldn't actually ship an app with NSZombieEnabled anyway. This is meant to be a debugging tool that you use at the debugger or within Instruments.
In your actual app, when you turn off NSZombie's, there still wouldn't be an exception to catch for this, since you would just get an EXE_BAD_ACCESS, which is a UNIX signal (not this type of an exception at this level).
The last point is that Objective-C exceptions (the type that you can #try/#catch) are not recommended for errors that you expect to be able to recover from. Or in other words, this is meant for fatal errors only, where you might do some cleanup and then allow your app to still crash.
The right way to do what you're trying to do is to actually test for different types or different values that you might except to get and then handle each case appropriately. You can do this using normal if/else conditionals or something of that sort. You can test values for nil if you need to and you can see if an object is of a particular class by using [someObj isKindOfClass:[MyExpectedClass class]]
I hope I understood the question correctly?
The problem is probably that you are releasing phone after assigning it to strContact, and then using strContact. The string object is probably getting deallocated when you release phone, so the pointer in strContact is no longer valid.
Are you sure that phone is a string? Looks like you're storing that object in a NSString* pointer 'strContact' that is probably not a string, hence the 'CFDictionary' in the error messages.
Looks like you have two problems to fix:
Getting the object of the right type.
Ensuring that you don't release objects before you need to. Try put the CFRelease after you've finished using the object!

iPhone app running in Instruments fails with unrecognized selector

I have an app that appears to run without problems in normal use. The Clang Static Analyzer reports no problems either. When I try to run it in Instruments, it fails with an unrecognized selector exception.
The offending line is a simple property setter of the form:
self.bar = baz;
To figure out what's going on, I added an NSLog() call immediately above it:
NSLog(#"class = %# responds = %d", [self class], [self respondsToSelector:#selector(setBar:)]);
self.bar = baz;
On the emulator (without Instruments) and on a device, this shows exactly what I'd expect:
class = Foo responds = 1
When running under Instruments, I get:
class = Foo responds = 0
I'm stumped as to what could cause this. Perhaps a different memory location is getting tromped on when it's in the Instruments environment? Can anyone suggest how I might debug this?
If bar belongs to self, can't you do bar=baz; ?
Check your properties.
Perhaps to you need a cast on baz?
There's not enough information here to know what's going on, but then, if you knew what information to provide you'd probably have already fixed it. So. A few things to check:
Is the "self" pointer being swizzled in any way? Try printing out the value of self at various points just for sanity's sake
When your code runs in Instruments, is it running in a different mode? (32-bit vs. 64-bit, Garbage collected vs. Retain-Release, etc.) I'm not sure why any of those would have an effect, but if it's running in a different mode, that's something to look into.
Are you synthesizing the setter correctly? Or is it being provided dynamically (via Core Data, etc.)? If you manually specify a setBar: method, do you still get the error?

iPhone development: How to Catch Exception/NSError in Objective-C?

I want my application to never just crash stupidly. I know that code quality is the root solution for this. But I still need an application to never crash when some unexpected bug happens. Here is code I want to try.
-(void)testException
{
#try
{
NSString* str;
[str release];
}
#catch(NSException* ex)
{
NSLog(#"Bug captured");
}
}
I know this one does not work. Because release never raise an exception. Here are my questions:
How to reach this kind of objective, bug will be captured, no crash?
How do I know which system library will raise exception and so I can write some code and know it works?
Here's what I have read
a. Exception Programming Topics for
Cocoa
b. Error Handling Programming
Guide For Cocoa
I come from an experienced Microsoft programmer background in which catch exception or unexpected exception always prevent my program from crashing in a very bad environment.
How did you guys/gals (Mac genius programmers) make crash free programs happened? Share your experience.
Objective-C is an unmanaged runtime; the code that you compile runs directly on the CPU rather than in a virtual machine. That means you don't have the supervisory layer that can trap every possible failure mode the way you do when running in the .NET VM or the JVM. The long and short of it is that the only way you're going to be completely sure a program can't crash is to code very carefully and test very thoroughly. And even then, you're not sure, you just think you are.
The latest version of Xcode integrates the Clang static analyzer ('Build and Analyze' in the Build menu) that can identity some classes of potential bugs -- I'm fairly sure it would flag your example above, for instance). But there is no magic bullet here; the only solution is hard work.
Test Test Test Test Test
You can spend all day writing exception-handling code for possible exceptions (that in practice will never occur), or you can create thorough test suites and only write exception handlers for situations that occur in practice.
This is why I almost never write exception handlers. If you fix the underlying issues that are causing the exception, then you don't need to handle anything.
Of course, there are situations where can't ensure that a method call won't cause an exception and you need to be prepared, but wrapping everything in #try/#catch blocks is definitely not the solution.
One issue you are having is that str is never initialized which means that str may be pointing to nil (but this is not guaranteed). It is definitely pointing to junk.
If you step through your code, I can almost guarantee that your release is being called on nil, which in Objective-C is completely valid.
Try doing this:
NSString *str = [[NSString alloc] initWithString:#"a string"];
[str release];
[str release];
Calling release does not deallocate an object, it simply decrements the retain count by 1. When an objects retain count is 0,
[self dealloc];
is called automatically.
If the above code does not throw an exception immediately, it may be because the actual deallocation message is delayed at some future point (I'm not sure exactly when dealloc is called after the retain count reaches 0. I think it is called immediately and on the same thread, but some other Cocoa ninja will know for sure).
What you can do is add a category to NSObject and implement the dealloc and release methods and try to catch you're exception in there.
- (void)dealloc{
#try
{
[super dealloc];
}
#catch(NSException* ex)
{
NSLog(#"Bug captured");
}
}
- (void)release{
#try
{
[super release];
}
#catch(NSException* ex)
{
NSLog(#"Bug captured");
}
}
The added bonus is that this code will be valid for every object in your app since it is a category on NSObject.
To be complete though, if you just practice them memory management rules, you will be fine.