Tuesday, June 29, 2010

Sending Messages to nil is Not Always Safe

I've been under the impression that in Objective-C sending messages to nil was always safe but learned recently that it is not always the case and wanted to share.

The conventional Objective-C wisdom says that sending messages to nil is safe (it acts as a noop) and returns nil for object return values and 0 or zero filled structs for scalar or struct return values.

As it turns out some scalars / structs will not be zeroed out which means they will contain random data.

The language Apple uses in their docs say that scalars are guaranteed to be zero only if the size of the return type is "less than or equal to sizeof(void*)" or the returned struct is "to be returned in registers" as "defined by the Mac OS X ABI Function Call Guide".

CGRect is an example of one that does not meet this criteria. As an example the following code:

UIViewController *viewController = nil;
UIView *view = [viewController view];
CGRect frame = [view frame];
NSLog(@"frame=%@", NSStringFromCGRect(frame));
will print out something like this:
frame={{1.6584e-37, -1.99876}, {6.19141e-39, 6.05479e-37}}
Long story short, take care when calling methods that return scalars / structs if the object you are messaging could be nil.

A good blog post on the topic is here:
http://vgable.com/blog/2008/05/31/messages-to-nowhere

In it he points out that the behavior can vary by platform / processor so what happens on the iPhone simulator may not be what happens on the actual device.

2 comments:

Dennis said...

Sending a message to nil is safe -- taking the return value may not be safe. If all you are doing is calling a method without needing a return value, there is absolutely nothing to be worried about. But as you've found, if you do care about the return value, it does matter -- for some types.

mpv said...

Seem to me to be a distinction without a difference.