1

I have a situation where I have copied a string in an instance of a helper class, retained it, and later released it during the dealloc of the view controller instance that alloc'd the helper class. This results in the dreaded EXC_BAD_ACCESS. I then went to Instruments to debug zombies. This gave me the following error:

An Objective-C message was sent to a deallocated 'CFString (immutable)' object (zombie) at address: blah blah

When I then look at the allocation summary within Instruments and work backwards from the zombie detection, the first time my code is listed is in the deallocation of the helper class instance. Here is what the helper class looks like. First the .h file:

@interface channelButtonTitles : NSObject {
    NSString *channelTitle;
    ...
}

@property (nonatomic,copy)  NSString *channelTitle;
...
@end

Then the .m file:

@implementation channelButtonTitles
@synthesize channelTitle;
...

- (void)dealloc {
    [channelTitle release];
    ...
}
@end

Now relevant code from the view controller that uses the helper class looks like the following. In the .h file I have an array that will hold multiple objects of the helper class as follows:

@interface MyVC : UIViewController {
    NSMutableArray *channelTitles;
    ...
}
@property (retain, nonatomic)   NSMutableArray *channelTitles;

Then in the .m code, I synthesize channelTitles. I also have a dealloc method as follows:

- (void)dealloc {
    [channelTitles release];
    ...
}

Finally, I alloc object instances of the helper class and store them in channelTitles with strings stored in the channelTitle elements of channelButtonTitles as follows:

[channelTitles removeAllObjects];
self.channelTitles = nil;
channelTitles = [[NSMutableArray alloc] init];
...

for (int i=0; i<numberOfTitles; i++) {
    // For each mediaItem, get the title and subtitle info
    channelButtonTitles *aChannelButtonTitle = [[channelButtonTitles alloc] init];  // create an object to hold the title and miscellaneous data
    aChannelButtonTitle.channelTitle = @"some title";

    [channelTitles addObject: aChannelButtonTitle]; // add the title
    [aChannelButtonTitle release];

}

So, this is a technique I have used many times before, but seems to not be happy now. When the view controller is popped and I return to the root view controller, the dealloc method in my view controller is called. That releases channelTitles which results in calling dealloc on the channelButtonTitles helper class objects that are stored in channelTitles.

Since I have used copy in the property of my helper class, I assume I own this string. Hence, I am releasing it. If I comment out the [channelTitle release] line from my dealloc, the EXC_BAD_ACCESS goes away, but I suspect I have a memory leak now. Please help me see what I am doing wrong.

jscs
  • 63,694
  • 13
  • 151
  • 195
JeffB6688
  • 3,782
  • 5
  • 38
  • 58
  • why are you not using arc? not a flip question (I had to support down to 10.5 recently), but i you can convert your stuff to arc/properties it will make your life easier – Grady Player Oct 28 '15 at 18:07
  • Did you try using the Static Analyzer? It is _really good_ at catching this sort of thing. – matt Oct 28 '15 at 18:10
  • @GradyPlayer This is an old app that started before arc. I just have been afraid to try to convert it. Have you ever converted a large software app to arc? If so, what was your experience? – JeffB6688 Oct 28 '15 at 18:36
  • @matt yes, that was the first thing I tried. It did not see a problem with this. – JeffB6688 Oct 28 '15 at 18:37
  • You need to look for places where you modify the `channelTitle` instance variable directly without going through the setter. One thing to try would be to refactor to rename that instance variable to `_channelTitle` which will make it easier to find such places. Also, make sure that nothing obtains the reference via the property getter and then releases it. For example `NSString* temp = whatever.channelTitle; ... [temp release];`. Or, perhaps another class has an `assign` property that it releases in its `-dealloc` and it gets assigned from `whatever.channelTitle`. – Ken Thomases Oct 28 '15 at 21:20

0 Answers0