views:

451

answers:

2

I have a problem that I am getting EX_BAD_ACCESS when calling release on an NSStream object in my dealloc on the iPhone.

The following code

- (void)dealloc {
    DLog(@"dealloc started for: %@",self);
    @synchronized(self) {
     lookupCount--;
 if (lookupCount==0) {
  UIApplication* app = [UIApplication sharedApplication];
  app.networkActivityIndicatorVisible = NO;
        }
    }
    DLog(@"inStream retain count before release: %d",[inStream retainCount]);
    [inStream release];
    DLog(@"outStream retain count before release: %d",[outStream retainCount]);
    [outStream release];
    [queryToSend release];
    [resultString release];
    [data release];
    [super dealloc];
    NSLog(@"dealloc finsihed for : %@",self);
    }

crashes with EX_BAD_ACCESS on the [outstream release]; line.

Log output is as follows

2009-04-29 13:16:28.547 App[30580:20b] -[SimpleQuery dealloc] [Line 160] dealloc started for: <SimpleQuery: 0x56e540>
2009-04-29 13:16:28.547 App[30580:20b] -[SimpleQuery dealloc] [Line 168] inStream retain count before release: 1
2009-04-29 13:16:28.548 App[30580:20b] -[SimpleQuery dealloc] [Line 170] outStream retain count before release: 1

Wondering if anyone has any ideas why this might be ?

A: 

Some potential problems:

  • You're locking on self to do the lookupCount decrement loop, which I assume means you expect this code to be run from different threads. That should be a red flag right there, since if you're deallocating an instance from two threads simultaneously, one of those threads is going to end up trying to dealloc an already deallocated instance.
  • The final NSLog call will try to print self which would already have been deallocated.

I know none of these pertains specifically to [outStream release], but they could be related. You might want to try debugging this with NSZombieEnabled to get more info.

Also, make sure releasing inStream doesn't also implicitly release outStream, etc.

Daniel Dickison
+1  A: 

In a comment you said this about outstream

It's created by a call to getStreamsToHostNamed:port:inputStream:outputStream: which shouldn't return autoreleased objects I don't think.

It is in fact, auto-released. Unless you are retaining that object somewhere in your code, you are not responsible for the memory management of it.

You should take a look at the Apple Memory Management Guidelines.

Many classes provide methods of the form +className... that you can use to obtain a new instance of the class. Often referred to as “convenience constructors”, these methods create a new instance of the class, initialize it, and return it for you to use. Although you might think you are responsible for releasing objects created in this manner, that is not the case according to the policy Cocoa set—the method name does not contain "alloc" or "copy", or begin with "new". Because the class creates the new object, it is responsible for disposing of the new object.

Jab
Thank you. This looks very much like my failure to grasp the difference between [self setStringVariable:aString]; self.stringVariable=aString;and stringVariable=aString;on synthasized retained variables.
Dean Smith