NSMutableArray传递参数内存泄漏

Cad*_*adu 2 cocoa-touch memory-leaks objective-c nsmutablearray

我在这里遇到一个难题,不管感谢,我的意思是任何帮助=)

我是一名经验丰富的开发人员,我是Objective-C/iPhone/Cocoa的新手.

我想创建一个类控制器,我可以将NSMutableArray作为参数传递.

然后,我们有:

selTimeIntController = [[SingleSelectPickerViewController alloc] initWithSettings: listOfIntervals :kAlarmIntervalStr :myDataHolder.alarmInterval];
[self.navigationController pushViewController: selTimeIntController animated: YES];
[selTimeIntController release];
Run Code Online (Sandbox Code Playgroud)

这个listOfIntervals是一个已经是alloc/init的NSMutableArray*.

在我的SingleSelectPickerViewController上,我们有:

-(id)initWithSettings:(NSMutableArray*)sourceArray :(NSString*)viewCurrentValue :(NSString*)viewTitle {

    if(self = [self initWithNibName: kNibName bundle: [NSBundle mainBundle]]) {

            listOfIntervals = [NSMutableArray arrayWithArray: (NSMutableArray*)sourceArray];
            currentValue    = [[NSString alloc] initWithString: viewCurrentValue];
            title           = [[NSString alloc] initWithString: viewTitle];
    }

    return self;
}
Run Code Online (Sandbox Code Playgroud)

通过调试,我能够在SingleSelectPickerViewController上看到我的listOfIntervals.

这里我们有SingleSelectPickerViewController'dealloc:

- (void)dealloc {
    [super dealloc];

    [listOfIntervals release];
    [currentValue    release];
    [title           release];
}
Run Code Online (Sandbox Code Playgroud)

但是,每次我实例化我的SingleSelectViewController时,我都会收到一个带有以下堆栈的EXEC_BAD_ADDRESS:

#0  0x96132688 in objc_msgSend ()
#1  0x00003ee2 in -[SingleSelectPickerViewController tableView:numberOfRowsInSection:] (self=0xd38940, _cmd=0x319a6bc0, tableView=0x102e000, section=0) at /Users/Cadu/iPhone/myApp/Classes/SingleSelectPickerViewController.m:115
#2  0x30a86bb4 in -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] ()
#3  0x30a8879b in -[UITableViewRowData rectForFooterInSection:] ()
#4  0x30a883c7 in -[UITableViewRowData heightForTable] ()
#5  0x3094e8e6 in -[UITableView(_UITableViewPrivate) _updateContentSize] ()
#6  0x30940a7d in -[UITableView noteNumberOfRowsChanged] ()
#7  0x3094a2a0 in -[UITableView reloadData] ()
#8  0x30947661 in -[UITableView layoutSubviews] ()
#9  0x00b41d94 in -[CALayer layoutSublayers] ()
#10 0x00b41b55 in CALayerLayoutIfNeeded ()
#11 0x00b413ae in CA::Context::commit_transaction ()
#12 0x00b41022 in CA::Transaction::commit ()
#13 0x00b492e0 in CA::Transaction::observer_callback ()
#14 0x30245c32 in __CFRunLoopDoObservers ()
#15 0x3024503f in CFRunLoopRunSpecific ()
#16 0x30244628 in CFRunLoopRunInMode ()
#17 0x32044c31 in GSEventRunModal ()
#18 0x32044cf6 in GSEventRun ()
#19 0x309021ee in UIApplicationMain ()
#20 0x000020d8 in main (argc=1, argv=0xbffff0b8) at /Users/Cadu/iPhone/MyApp/
Run Code Online (Sandbox Code Playgroud)

知道发生了什么事吗?

bbu*_*bum 7

问题的标题是"内存泄漏".问题中的所有内容都表示"崩溃".这是一个崩溃,而不是内存泄漏.或者,至少,在修复crashers之前,你不会知道是否有内存泄漏.

最可能的崩溃源是listOfIntervals实例变量的错误管理.

listOfIntervals = [NSMutableArray arrayWithArray: (NSMutableArray*)sourceArray];
Run Code Online (Sandbox Code Playgroud)

具体来说,这需要是:

listOfIntervals = [[NSMutableArray arrayWithArray: sourceArray] retain];
Run Code Online (Sandbox Code Playgroud)

正如迈克上面指出的那样,传递一个可变的集合参考可能是一个坏主意.如果sourceArray从班级下面改变怎么办?你准备好应对吗?

一个更常见的习惯用法是将你的方法声明为采用NSArray*然后复制数组:

listOfIntervals = [sourceArray mutableCopy]; // or -copy, if you don't need it to be mutable
Run Code Online (Sandbox Code Playgroud)

(1)(NSMutableArray*)演员是不必要的.知道伤害,但如果不需要它,为什么要这样做呢?

(2)您需要保留listOfIntervals.+ arrayWithArray:将创建一个自动释放的数组,因此,该数组released在对象初始化之后,这将导致您看到的崩溃.

(3)-copy&-mutableCopy返回保留的对象,无需调用-retain.

但是,您还需要修复-dealloc方法:

- (void)dealloc {
    // move this [super dealloc];

    [listOfIntervals release];
    [currentValue    release];
    [title           release];
    [super dealloc]; // to here
}
Run Code Online (Sandbox Code Playgroud)

[super dealloc] 必须始终是最后一个.-dealloc并没有什么神奇之处,因此,通过首先调用该函数,您告诉实例释放自己然后通过并清理实例变量.这将导致第二次崩溃(或意外行为).

总的来说,我建议你重新阅读内存管理指南.

http://developer.apple.com/iPhone/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html