NSLog crashes when sent a nil value inside a ios 10.0.2 enviroment

I'm doing maintenance for a pretty old app dating back to iOS 7-8, however when my coworker was debuging it in his iOS device using iOS10 it crashes whenever a NSLog is sent a nil value NSString.

Replies

I was unable to reproduce the problem here in my office. Here’s what I did:

  1. On 10.11.6 using Xcode 8, I created a new test project from the Single View Application template.

  2. I changed

    -application:didFinishLaunchingWithOptions:
    as shown below.

    Note This somewhat convoluted code ensures that the compiled doesn’t do any clever optimisations; it can’t know that

    str
    will be nil.
  3. I ran it, both from Xcode and from the home screen.

In both cases it successfully logged the nil:

2016-10-12 11:41:18.282551 xxos[972:565782] QQQ (null)

I’m not sure what’s going on in your app but I’m pretty sure that the issue is not as simple as a bug in

NSLog
’s handling of nil.

Perhaps you can post a snippet of code that reproduces the problem? Or a crash log?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    NSData * data = [NSData dataWithBytes:"\x80" length:1];
    NSString * str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"QQQ %@", str);
    return YES;
}

I see a similar case, app works fine when compiled w/ xcode 7.3 with stuff like NSLog([error localizedDescription]) if error is nil

(e.g. no format string)


but when compiling w/ xcode8.3.3, the above crashes, seemingly because it is trying to do NSLog(nil)


is this a new change, cannot pass nil as the only string to NSLog?


any quick fixes that anybody knows about?

Can you give some details of the crash?

it looks like a standard issue dereference null pointer in lower level printf code getting called


EXC_BAD_ACCESS (code=1, address=0x0)


i dont have the stack trace offhand. it's as if in older iOS levels, NSLog could handle you passing it nil okay, but

maybe it was rewritten for ios10 and now this is not allowed?

It was likely changed to use the new OS logging system introduced around that time, and the os_whatever method it calls (being C) likely doesn't tolerate nils. A partial backtrace would indicate if that's what happened.


I'm not sure what kind of quick fix you were hoping for. At the source code level? The linker? Run-time? You might be able to play some kind of linker game with the external symbol to substitute a customized version of NSLog. You might be able to catch the crash at run time and continue execution. It doesn't seem promising, though.

FYI if anyone is interested, to temp work around these crashes, we edited the project's .pch file to add this:


#define NSLog(...)


to quickly get the project running again


if we really needed a log in the code like for logging stuff not easy to print with printf, we wrap the NSLog statement like this


#undef NSLog

NSLog(@"this is the log we need");

#define NSLog(...)

A comment on the earlier discussion which never seemed to have concluded anything....


"NSLog([error localizedDescription]) if error is nil".


If it turns out "error" is not nil but rather something that has been deallocated or an NSString then sending it the message "localizedDescription" will create an error as NSLog tries to value its operand