bacar
bacar

Reputation: 10091

Are pointers always set to nil on declaration?

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

Answers (4)

justin
justin

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?

  1. Uninitialized
  2. An objc instance which has been allocated, but has not been initialized (not safe to use otherwise)
  3. An initialized objc instance or object.

Upvotes: 6

sanjeev bharti
sanjeev bharti

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

UIAdam
UIAdam

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

Lily Ballard
Lily Ballard

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

Related Questions