Note that there are some explanatory texts on larger screens.

plurals
  1. POPlugging a sortedArrayUsingSelector and/or initWithArray Memory Leak Between Classes
    primarykey
    data
    text
    <p>I've been struggling to solve this memory leak for awhile now, so I'm hoping the community can provide some help. Memory Management is still an issue I'm working to understand (and yes I have the memory management guide).</p> <p>According to the Instruments Leak tool, I'm leaking an NSArray as soon as I navigate backward (back button w/ Nav Controller) off of the pertinent screen. I'm show all the relevant code I can think of, below, and can share more if needed.</p> <p>I know that I'm alloc/initing an array in the ordered array function. This is because, to the best of my understanding, <code>sortedArrayUsingSelector</code> returns only pointers to the old array, not a true copy, so if I want to keep the array, I need to copy the values.</p> <p>The problem is then how do I pass this sorted array to a different class while still properly managing my ownership of it? I release it in the dealloc, and I release it if the function is going to assign a new value, etc. But tbh I don't know if I'm doing this correctly.</p> <p>Like I said, I'm really struggling still to properly understand how to correctly juggle all the memory management stuff, so any help would be much appreciated. </p> <p><strong>.h file of the relevant model class</strong></p> <pre><code>@interface InstalledDataTracker : NSObject { ...other code... NSArray *orderedZonesArray; ...other code... } @property (nonatomic, retain) NSArray *orderedZonesArray; </code></pre> <p><strong>.m file of the relevant model class</strong></p> <pre><code>@synthesize orderedZonesArray; ...other code... - (NSArray *)orderedZonesArray { if (!orderedZonesArray || installedDataChangedSinceLastRead) { if (orderedZonesArray) { [orderedZonesArray release]; } NSArray *unorderedZones = [NSArray arrayWithArray:[self.installedAreas allKeys]]; orderedZonesArray = [[NSArray alloc] initWithArray:[unorderedZones sortedArrayUsingSelector:@selector(localizedCompare:)]]; } return orderedZonesArray; } - (void) dealloc { ...other code... [orderedZonesArray release], orderedZonesArray = nil; [super dealloc]; } </code></pre> <p><strong>.h in View Controller</strong></p> <pre><code>#import &lt;UIKit/UIKit.h&gt; @class InstalledDataTracker; @interface SBVC_LSC01_ZoneSelect : UIViewController &lt;UITableViewDataSource, UITableViewDelegate&gt; { ... other stuff... InstalledDataTracker *_dataTracker; } @property (nonatomic, retain) InstalledDataTracker *dataTracker; </code></pre> <p><strong>.m init in View Controller</strong></p> <pre><code>@synthesize dataTracker = _dataTracker; - (id)initWithPerson:(NSString *)person { if (self = [super init]) { ...other stuff... self.dataTracker = [[InstalledDataTracker alloc] init]; } return self; } - (void)dealloc { ...other stuff... [self.dataTracker release]; [super dealloc]; } </code></pre> <p><strong>Leaking Method in View Controller</strong></p> <pre><code>- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } AbbreviationLookup *lookup = [[AbbreviationLookup alloc] init]; NSString *abbreviatedZone = [self.dataTracker.orderedZonesArray objectAtIndex:[indexPath section]]; cell.textLabel.text = [lookup zoneForAbbreviation:abbreviatedZone]; [lookup release]; return cell; } </code></pre> <p><strong>Instruments Leak Trace:</strong></p> <pre><code>0 libSystem.B.dylib calloc 1 libobjc.A.dylib class_createInstance 2 CoreFoundation __CFAllocateObject2 3 CoreFoundation +[__NSArrayI __new::] 4 CoreFoundation -[NSArray initWithArray:range:copyItems:] 5 CoreFoundation -[NSArray initWithArray:] 6 -[InstalledDataTracker orderedZonesArray] 7 -[SBVC_LSC01_ZoneSelect tableView:cellForRowAtIndexPath:] </code></pre> <p><strong>Things I've tried</strong></p> <pre><code>orderedZonesArray = [[[NSArray alloc] initWithArray:[unorderedZones sortedArrayUsingSelector:@selector(localizedCompare:)]] autorelease]; </code></pre> <p><code>return [orderedZonesArray autorelease];</code></p> <p>And a bunch of other stuff I can't remember. Many attempts I've made to properly "release" the ownership created by alloc/init result in some sort of crash/bad access in the view controller. This is contributing to my confusion over where to properly release the array...</p> <p>Detailed replies very welcome. I still have a great deal to learn!</p> <p>Thanks a bunch. (Also, I've had to change some class and methods names for project security, so if something doesn't seem to match please mention it and I'll recheck for a typo)</p> <p><strong>Edit:</strong></p> <p>@Daniel Hicks, when I remove the <code>initWithArray</code> copy of the sorted array, as follows: </p> <pre><code>orderedZonesArray = [unorderedZones sortedArrayUsingSelector:@selector(localizedCompare:)]; </code></pre> <p>, I get an EXC_BAD_ACCESS crash when the class tries to access the array from within the View Controller <code>didSelectRowAtIndexPath</code> method (likely the next time the array is accessed, I believe). Here's the method. It crashes on the second NSLog line, so I've left that in for good measure:</p> <pre><code>- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"indexPath = %@", indexPath); NSLog(@"self.dataTracker.orderedZonesArray = %@", self.dataTracker.orderedZonesArray); NSString *abbreviatedZone = [self.dataTracker.orderedZonesArray objectAtIndex:[indexPath section]]; SBVC_LSC02_ZoneSelect *slz2 = [[SBVC_LSC02_ZoneSelect alloc] initWithPerson:self.selectedPerson andZone:abbreviatedZone]; [self.navigationController pushViewController:slz2 animated:YES]; [slz2 release]; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload