Diagnosing EXC_BAD_INSTRUCTION in Swift standard library - swift

My Swift application running in iOS simulator is being stopped in debugger with runtime error EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, sub code=0x0).
According to the WWDC 2014 Session 409 this is typically due to assertion failure.
In the current development Beta version of Xcode 6, the debugger’s stack trace and the above error does not provide enough information to see what the issue is. How do I find out where the problem is?

It appears that the most common source of this error (at the time of this writing: Xcode 6 Beta 1) is that some implicitly unwrapped optional property or variable is nil.
For convenience, most Objective-C API are bridged to Swift with implicitly unwrapped optionals. They are denoted by exclamation mark behind the type declaration: AnyObject[]!
If the debugger stops in your code, double-check that line and look for implicitly unwrapped optionals that could be nil there.
Sometimes the debugger stops with that runtime error deep in Swift system library. This happens for example when you pass a closure to collection methods like filter, map, reduce et al. The runtime error then occurs at the call site of those library functions, but the definition might be in different parts of your code, where you defined the function/closure. Look there for implicitly unwrapped optionals that might be nil at runtime.
To guard agains these kinds of error be aware that even though Swift compiler will not force you to handle the potential nil values returned from Cocoa, you should use optional binding, optional chaining
or optional downcasting wherever the return value from Objective-C land might be nil.
Let’s hope that future versions of Swift compiler will start emitting more helpful diagnostic messages and errors for this common type of problem!

I have found (after many hours) that this error can appear on the wrong line.
For example
As you can see the app is crashing where I am checking for nil, but then 'continuing' through because it prints the statements. It then goes 'backwards' and crashes.
I've come to the conclusion that there is a source-mapping bug in XCode (7) where a nil variable is un-wrapped. In this case, I had a variable (much farther down in my code) that was nil and being unwrapped.
The problem of course is that the compiler didn't flag the actual variable that was nil, it flagged something else entirely.
So if you run into this nasty bug, go through all possible variables that can be nil and check them for unwrapping. You are likely unwrapping a nil, its just not the one the compiler says.
As mentioned in the comment there is compiler optimization. Here is a link to fix the issue (and find the route cause of the crash)
xcode 6.1 how to disable optimization (Swift)

I had the same issue as Palimondo. Fortunately, it was simply a matter of making sure that I had initialized the item ahead of time. In my code, I was calling a function to place images in UIImageViews and passing in an element from an array. I had not yet loaded my array with the UIImageViews, and therefore when the code would run it would say that I was passing in a nonexistent element of the array. Once I made sure to load up my array at the start of the program the error went away.

Related

How to test for undefined array?

I am using this line of code
let transactions = SKPaymentQueue.default().transactions
This is what Apple amazing docs has to say about transactions.
What is exactly "undefined"? How do I test transactions before proceeding in code?
I have an observed attached to the payment queue.
I can guarantee you that undefined is not nil, because I have tested for nil and Xcode whined with an error
Comparing non-optional value of type '[SKPaymentTransaction]' to 'nil' always returns false
is undefined the new "empty array"? If not, how do I test for that?
Undefined means literally that: the API does not define what the framework will do. Anything is "fair game".
The code might cause a fatal error, return an empty array, or trigger a workflow to send a postcard to you in the mail. It's not defined.
However, no matter what the current behaviour happens to be, you shouldn't depend on it. It might return an empty array today, but crash tomorrow. Because the API explicitly documents the behaviour as undefined, Apple is free to change implementation details, without them counting as "API breaking changes".

Break on any occurrence of "fatal error: unexpectedly found nil while unwrapping an Optional value"

I have a huge code base and I want to break on the error "fatal error: unexpectedly found nil while unwrapping an Optional value"
What is the best approach to do that?
I tried adding both: (In the breakpoints sub-window)
"Add Swift Error Breakpoint"
"Add Exception Breakpoint"
But that didn't do it. Does that mean that the nil was in some framework code and not my code?
Unwrapping optionals gets translated by the compiler into calls to _getOptionalValue(), which calls _preconditionFailure() in case of anil value, which gets translated into a call to _fatalErrorMessage().
So you need to set breakpoints for _fatalErrorMessage. The trick here is that you need to set the breakpoints for the mangled name of the function, which is _TTSf4s_s_d_d___TFSs18_fatalErrorMessageFTVSs12StaticStringS_S_Su_T_.
If you add a symbolic breakpoint for this, the breakpoint will be hit everytime a fatal error occurs. This means you'll catch all nil unwraps, however you'll also catch some other pieces of code that trigger fatal errors. You should be able to set some conditions on the arguments of the function so that your breakpoint is hit only when the unexpectedly found nil while unwrapping an Optional value is passed, however I personally didn't played with this feature of lldb so I'm not sure how you need to set this condition in the breakpoint editor.
Update. In Swift 3 (Xcode 8 beta 6), the breakpoint should be set for _TTSfq4n_n_d_d_n___TFs18_fatalErrorMessageFTVs12StaticStringS_S_Su5flagsVs6UInt32_Os5Never
Here's how you can find out for your own the mangled function name for any Swift version, in order to set a breakpoint to:
Find you build app location (can be easily found in Xcode Navigator -> Products -> Your App Name.app)
List all your global symbols for the libswiftCore.dylib embeded within your app bundle, grep by fatalError. So for example if your build app is at /Users/your.username/Library/Developer/Xcode/DerivedData/YourApp-randomchars/Build/Products/Debug-iphonesimulator/YourApp.app/, you should run
nm -g /Users/your.username/Library/Developer/Xcode/DerivedData/YourApp-randomchars/Build/Products/Debug-iphonesimulator/YourApp.app//Frameworks/libswiftCore.dylib | grep fatalError
Check the output and grab the mangled method names. There could be more than one symbol, if the function is overloaded. A sample output looks like this:
0000000000032f50 T __TFs18_fatalErrorMessageFTVs12StaticStringS_S_Su5flagsVs6UInt32_Os5Never
00000000001663b0 T __TTSfq4n_n_d_d_n___TFs18_fatalErrorMessageFTVs12StaticStringS_S_Su5flagsVs6UInt32_Os5Never
Make sure you remove the leading underscore before adding the breakpoint, that one comes from the C name mangling (so for the above output you should remain with only one leading underscore for the two symbols).
Add the breakpoints and force unwrap a nil value, to make sure they work.
Happy nil-unwrapping hunting :)

"Initialisation of immutable value'context' was never used, consider replacing assignment to '_' or removing it

In swift I declared a variable as
let context:LAContext = LAContext()
It throws a warning
"Initialisation of immutable value'context' was never used, consider replacing assignment to '_' or removing it.
It's all in the error message
value...was never used
Your variable isn't being used anywhere, so Xcode tells you that you can remove it (because having unused variables is a waste of memory). Just use your variable somewhere and the error will go away (e.g. get a value from it, print it, etc).
Of course you mean to use it somewhere right? Otherwise you wouldn't have declared it. It's just that the Xcode (especially the new one, I noticed) checks for errors immediately, so these kinds of errors appear before you can really do anything about it.
Edit: I didn't imagine that almost 7 years later people would still be commenting on a post regarding a beginner-level compiler warning, but to be more specific, yes there are some cases where you might not want to keep a variable around or where you want to discard some return value, so you don't necessarily always "mean to use it somewhere". See comments for more.

fatal error: unexpectedly found nil while unwrapping an Optional value While unwrapping SKSpriteNode

I am getting the following error at the mentioned line of code
Even though the debugger shows that bg has been assigned a value, that it fetches from .sks file. (GameScene.sks file contains an object named as bg)
Any help would be highly appreciated.
-> -> EDIT
Whilst no thanks to the community here thats full of people who'd just try to be uncanningly witty and gods of humor, i managed to figure it out myself. So for a future reference if someone else falls in the same situation, i am sharing the code that was the reason for the problematic error.
At this point in time the debugger will show a value for bg that was previously there on the stack (garbage in the memory).
It will never write something to bg because the program crashes while evaluating the value for the variable so you are just seeing garbage.
The error you can see clearly means there is no node named bg.

On iOS, the if() statement has different result between release version and debug version

I have an app submitted to Apple Store, and it passed. But I found there was a bug will make the app crash. Finally, I found the real problem is a snap of code has the opposite result.
code:
CGPoint now;
CGPoint old;
UIView *lastDot;
now = dotView.center;
if(lastDot){
//release version, will go here. then crashed.
old = lastDot.center;
}else{
//debug version, will go here. run ok.
}
I declare a UIView pointer, and check it with "if statement",
UIView *lastDot;
the debug version consider the lastDot as nil, but the release version think is not null.
can anyone give me any idea? thank you.
Depending on your compiler settings, debug builds usually initialize pointers to some sentinel values like 0xcccccccc.
UIView *lastDot = nil;
Should work as expected.
The issue is due to uninitialized pointer.
Initialize it to nil for avoiding such troubles.
UIView *lastDot = nil;
I know you already got the answer.
I just want to add some points too:
Pointers are just like any other variable: if you don't explicitly set
them to a value, the value will be undefined means a random value. If
you then accidentally access the variable, very bad things can happen.
Sometimes people recommend that pointers be assigned to NULL, the
universal value meaning "this pointer doesn't point at anything",
because a lot of code already checks for NULL pointers. For example,
if you call [nil release], it's guaranteed to do nothing. If you
passed an uninitialized pointer in who knows what would happen.
It's really just a safeguard against programmer error. If you
initialize pointers to a reasonable value, it's less likely that an
uninitialized pointer will cause a system crash sometime in the
future.
When you don't initialize a pointer and then try to use it, you have 3
problems:
It might be pointing at memory you don't have access to, in which case it causes a segmentation fault and crashes your program
It might be pointing at real data, and if you don't know what it's pointing to, you're causing unpredictable (and very hard to debug)
changes to your data.
You have no way of knowing if it's been initialized or not - because how do you tell the difference between a valid address and the address
that happened to be there when you declared the pointer?
Initializing every pointer to nil seriously decreases or eliminates
those problems:
If I try and use it, it will still segfault, but at least I can test if it's NULL and act accordingly - I can know that it WILL segfault,
and do something else. If it's a random value, I don't know anything
until it crashes.
If you initialize it to nil, I can't make it point to data unless I explicitly tell it to. So I only modify what I meant to.
As implied above, I can tell when I've initialized it and when I haven't, and make a decision.
Obviously it's a matter of style, and it is possible to write an
application where variables are only initialized to their intended
value, but I feel it is safer and easier to initialize them to nil
always. Even the best programmers make typos - nil makes it easier
to know when that's happened.
Reference :
eskimo
Initializing pointers always necessary