在类之间插入sortedArrayUsingSelector和/或initWithArray内存泄漏 [英] Plugging a sortedArrayUsingSelector and/or initWithArray Memory Leak Between Classes

查看:89
本文介绍了在类之间插入sortedArrayUsingSelector和/或initWithArray内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一段时间以来,我一直在努力解决此内存泄漏问题,因此,我希望社区能够提供一些帮助.内存管理仍然是我要了解的问题(是的,我有内存管理指南).

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).

根据Instruments Leak工具,一旦从相关屏幕上向后导航(带有Nav Controller的后退按钮),我就会泄漏NSArray.我在下面展示了我能想到的所有相关代码,并在需要时可以共享更多代码.

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.

我知道我在有序数组函数中分配/初始化一个数组.这是因为,据我所知,sortedArrayUsingSelector仅返回指向旧数组的指针,而不是真正的副本,因此,如果要保留该数组,则需要复制值.

I know that I'm alloc/initing an array in the ordered array function. This is because, to the best of my understanding, sortedArrayUsingSelector 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.

然后的问题是,如何在仍然正确管理其所有权的同时,将经过排序的数组传递给另一个类?我在dealloc中释放了它,如果该函数打算分配一个新值,则释放了它,等等.但是tbh我不知道我是否正确执行了此操作.

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.

就像我说的那样,我真的仍在努力地正确理解如何正确处理所有内存管理方面的内容,因此,我们将不胜感激.

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.

.h文件

@interface InstalledDataTracker : NSObject {

    ...other code...

    NSArray *orderedZonesArray;

    ...other code...
}

@property (nonatomic, retain) NSArray *orderedZonesArray;

相关模型类的

.m文件

@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];
}

.h在View Controller中

#import <UIKit/UIKit.h>

@class InstalledDataTracker;

@interface SBVC_LSC01_ZoneSelect : UIViewController <UITableViewDataSource, UITableViewDelegate> {

    ... other stuff...

    InstalledDataTracker *_dataTracker;
}

@property (nonatomic, retain) InstalledDataTracker *dataTracker;

.m in View Controller中的初始化

@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];
}

View Controller中的泄漏方法

- (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;

}

仪器泄漏跟踪:

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:]

我尝试过的事情

orderedZonesArray = [[[NSArray alloc] initWithArray:[unorderedZones sortedArrayUsingSelector:@selector(localizedCompare:)]] autorelease];

return [orderedZonesArray autorelease];

还有其他我不记得的东西.我为正确释放"由alloc/init创建的所有权而进行的许多尝试都导致视图控制器中发生某种崩溃/错误的访问.这加剧了我在哪里正确释放阵列的困惑.

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...

详细回复非常欢迎.我还有很多东西要学习!

Detailed replies very welcome. I still have a great deal to learn!

谢谢. (此外,为了项目安全,我必须更改一些类和方法的名称,因此,如果某些内容看起来不匹配,请提及它,我将再次检查是否有错字)

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)

@Daniel Hicks,当我删除排序数组的initWithArray副本时,如下所示:

@Daniel Hicks, when I remove the initWithArray copy of the sorted array, as follows:

orderedZonesArray = [unorderedZones sortedArrayUsingSelector:@selector(localizedCompare:)];

,当类尝试从View Controller didSelectRowAtIndexPath方法中访问数组时,我遇到EXC_BAD_ACCESS崩溃(我相信下次可能会访问数组).这是方法.它在第二行NSLog上崩溃,因此我将其留给了充分的措施:

, I get an EXC_BAD_ACCESS crash when the class tries to access the array from within the View Controller didSelectRowAtIndexPath 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:

- (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];

}

推荐答案

在您的viewController代码中,分配一个InstalledDataTracker对象,然后将其传递给keep属性.这样会导致保留计数为2,而不是1.稍后,当释放dataTracker对象时,只能将保留计数减少1.

In your viewController code, you allocate an InstalledDataTracker object, and then pass it to a retain property. This results in a retain count of 2, not 1. Later, when you release the dataTracker object, you only reduce the retain count by one.

最简单的解决方法是删除self.前缀,这样您就不会 调用由属性访问器执行的自动retain.实际上,我建议您在initdealloc方法中完全不要使用点语法.关于此事有一些争论,但是总的来说,我认为最好避免致电您的财产访问者,除非您有充分的理由这样做.

The easiest way to fix it would be to remove the self. prefix so that you are not invoking the automatic retain that is performed by the property accessor. In fact, I would recommend not using the dot syntax at all in your init and dealloc methods. There is some debate on the matter, but in general I think it is best to avoid calling your property accessors unless you have a very good reason to do so.

这是我的写法:

- (id)initWithPerson:(NSString *)person {
    if (self = [super init]) {
        ...other stuff...

        dataTracker = [[InstalledDataTracker alloc] init];
    }
    return self;
}

- (void)dealloc {
    ...other stuff...
    [dataTracker release];
    [super dealloc];
}

这篇关于在类之间插入sortedArrayUsingSelector和/或initWithArray内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆