1

I'm new to Objective C. I see in many iPhone/iPad applications that after releasing an object, it would then be set to nil.

[self.obj release]
self.obj = nil; 

I assume this is done so as not to leave the pointer to reference a memory location that is now deallocated. Now assume the following situation:

//Thread #1 code
..some code
..some code
[self.obj release]
                  -------> Thread #2 runs //Thread #2 code
                                          ..some code
                                          if (self.obj){
                                            some code
                                          }
self.obj = nil;   <----- Thread #1 runs

I was wondering if this situation possible? And if it is, is there a way to make the release/nil atomic?

DBD
  • 23,075
  • 12
  • 60
  • 84
Just a coder
  • 15,480
  • 16
  • 85
  • 138

3 Answers3

5

this is actually not entirely correct

[self.obj release]
self.obj = nil;

you should write simply

self.obj = nil;

which will call the setter that will release the previous instance.

AndersK
  • 35,813
  • 6
  • 60
  • 86
  • This is correct provided the nonatomic attribute isn't set on the obj property. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html – Joel Dec 19 '11 at 20:59
  • Yes, i realize.. Look below at my comment @DBD 's post. I made the properties non atomic. Thanks tho :) – Just a coder Dec 19 '11 at 21:51
4

Yes, it could blow up. Consider your code example.

[self.obj release];
self.obj = nil;

You use self.obj which means you are referencing accessor/mutators methods instead of accessing your object directly. Chances are you'd declare "obj" as a retained property. Your .h would be something like...

@property (retain) Something *obj;

and your .m

@synthesize obj;

If you later release your object by using the methods created by your @synthesize you are safe.

[self setObj:nil];
// or equally valid
self.obj = nil;
// Below is (almost) identical way to access, release and nil the variable directly.
// The major difference is you don't multi-threaded protection of your property
// declaration (explained below).
[obj release];
obj = nil;

If you look back at the property I specified above you'll notice I didn't put in the very commonly seen nonatomic. It wasn't by accident. Take a look at Apple's docs

Properties are atomic by default so that synthesized accessors provide robust access to properties in a multithreaded environment—that is, the value returned from the getter or set via the setter is always fully retrieved or set regardless of what other threads are executing concurrently.

DBD
  • 23,075
  • 12
  • 60
  • 84
  • Thanks, I have a chosen a combination of yours and Anders's answer above. I will use **self.obj = nil;** which will invoke the setter to release the old value. Also, i will set the @property to be atomic like you said. I chose his answer tho.. only one correct answer can be chosen > – Just a coder Dec 19 '11 at 20:47
1

You can surround both operations in an @synchronized block to ensure that both operations complete before leaving the block:

@synchronized(lockObject)
{
    [self.obj release];
    self.obj = nil;
}

Provided that any other threads that might access that variable also synchronize around the same lock object, you shouldn't run into any issues.

Matthew W
  • 197
  • 1
  • 8
  • 1
    Good point. Thanks, but i went with setting he property as atomic as mentioned below. – Just a coder Dec 19 '11 at 20:49
  • Sending `release` to the result of an accessor call isn't the best idea. See: http://stackoverflow.com/questions/7262268/why-shouldnt-i-use-the-getter-to-release-a-property-in-objective-c – jscs Dec 19 '11 at 21:59