Reputation: 10091
I've found various people/articles (e.g. this SO answer) suggesting that the value of pointers in Objective-C is not defined until you assign something to it. However, I'm finding in practice that they are automatically set to nil
even before I call alloc
- the following code runs for me without asserting:
NSString* foo; // 1
assert(foo==nil); // foo is nil
foo = [NSString alloc]; // 2
assert(foo!=nil); // after alloc, not nil.
foo = [foo init]; // 3
assert(foo!=nil); // still not nil
Can/should I rely on this? Is it guaranteed or do I just happen to be running my compiler (Xcode) in some sort of debug mode? (I'm new to Objective-C).
A corollary question: what is the correct terminology to describe foo
in the state at the end of the lines marked 1, 2 and 3? I imagine at least one of 1 & 2 them is termed 'uninitialised', and one of 2 & 3 is 'initialised', but which, and what do we call the third option?
Upvotes: 15
Views: 6328
Reputation: 104698
(For ARC, see Lily Ballard's answer)
Can/should I rely on this?
Nope - never rely on that. Stack memory is typically zeroed in debug builds (depends on your compiler settings). With optimization enabled, the compiler does not do that for you and you'll be given garbage values based on whatever happened to exist on the stack region last.
You can rely on zeroed ivars in your objects' initializers.
You can guard yourself from this with the static analyzer, and by enabling -Wuninitialized
for your build configs when the optimization level is greater than -O0
.
A corollary question: what is the correct terminology to describe foo in the state at the end of the lines marked 1, 2 and 3? I imagine at least one of 1 & 2 them is termed 'uninitialised', and one of 2 & 3 is 'initialised', but which, and what do we call the third option?
Upvotes: 6
Reputation: 1
In ARC Environment objects are automatically set to nil. But it always a good practice to Assign value to objects during initialization.
I just ran a test with obj-c in ARC environment
NSString *testStr ;
if (testStr == nil) {
NSLog(@"Test Successful");
}
OutPut :
Test Successful
NSString *testStr = nil;
if (testStr == nil) {
NSLog(@"Test Successful");
}
OutPut :
Test Successful
Upvotes: 0
Reputation: 5313
An answer to your corollary question:
After #1, foo has been declared but is uninitialized.
After #2, foo has been allocated but is still uninitialized.
After #3, foo has been initialized.
In practice, you never want to separate steps 2 and 3, that is your code should be foo = [[NSString alloc] init]
. The reason for this is that it is "dangerous" to allocate an object and not initialize it, or to initialize it improperly.
If you just do this foo = [NSString alloc]
but forget to ever call init, it is not safe to use foo since it hasn't been initialized. Likewise, it is equally unsafe to do this [foo init]
(notice the lack of reassignment to foo) because init can return a different reference to the initialized object than was originally allocated by alloc.
Upvotes: 1
Reputation: 185721
Under ARC, all object pointers are set to nil
upon initialization. When not running under ARC, or when using pointers to other datatypes, an uninitialized pointer will have a garbage value (and in fact reading from the pointer produces undefined behavior according to the C standard).
@Chuck points out something important, which is that this only applies to local variables. Any variable with static storage (function statics, or globals) and instance variables are always initialized to their respective zero value (which, for pointers, is nil
/NULL
).
Upvotes: 33