- What is the normal behavior in Objective-C if you call a method on an object (pointer) that is nil (maybe because someone forgot to initialize it)? Shouldn't it generate some kind of an error (segmentation fault, null pointer exception...)?
- If this is normal behavior, is there a way of changing this behavior (by configuring the compiler) so that the program raises some kind of error / exception at runtime?
To make it more clear what I am talking about, here's an example.
Having this class:
@interface Person : NSObject {
NSString *name;
}
@property (nonatomic, retain) NSString *name;
- (void)sayHi;
@end
with this implementation:
@implementation Person
@synthesize name;
- (void)dealloc {
[name release];
[super dealloc];
}
- (void)sayHi {
NSLog(@"Hello");
NSLog(@"My name is %@.", name);
}
@end
Somewhere in the program I do this:
Person *person = nil;
//person = [[Person alloc] init]; // let's say I comment this line
person.name = @"Mike"; // shouldn't I get an error here?
[person sayHi]; // and here
[person release]; // and here
A message sent to a nil
object is perfectly acceptable in Objective-C, it's treated as a no-op. There is no way to flag it as an error because it's not an error, in fact it can be a very useful feature of the language.
From the docs:
Sending Messages to nil
In Objective-C, it is valid to send a
message to nil—it simply has no effect
at runtime. There are several patterns
in Cocoa that take advantage of this
fact. The value returned from a
message to nil may also be valid:
If the method returns an object, then a message sent to nil
returns
0
(nil
), for example:
Person *motherInLaw = [[aPerson spouse] mother];
If aPerson
’s spouse
is nil
,
then mother
is sent to nil
and the
method returns nil
.
If the method returns any pointer type, any integer scalar of size less
than or equal to sizeof(void*)
, a
float
, a double
, a long double
,
or a long long
, then a message sent
to nil
returns 0
.
If the method returns a struct
, as defined by the Mac OS X ABI
Function Call Guide to be returned in
registers, then a message sent to
nil
returns 0.0
for every field in
the data structure. Other struct
data types will not be filled with
zeros.
If the method returns anything other than the aforementioned value
types the return value of a message
sent to nil is undefined.
From Greg Parker's site:
If running LLVM Compiler 3.0 (Xcode 4.2) or later
Messages to nil with return type | return
Integers up to 64 bits | 0
Floating-point up to long double | 0.0
Pointers | nil
Structs | {0}
Any _Complex type | {0, 0}
One thing you should be clear on is that in Objective-C, you don't call a method on an object, you send a message to an object. The runtime will find the method and call it.
Since the first versions of Objective-C, a message to nil has always been a safe no-op that returns nil. There's a lot of code that depends on this behavior.