NSArray深层复制导致崩溃

时间:2011-10-07 17:38:47

标签: objective-c ios nsmutablearray nsarray deep-copy

我现在已经盯着这段代码了一段时间,但无法弄清楚世界上有什么不对。我有一个名为SortFilteringController的类,它管理我在系统中的不同过滤(内部过滤器,公共过滤器,排序选项等)。其中每个都存储在一个数组中。所以我有一个方便的方法,它基本上采用任何这些数组,并用一些新数据重置它们。

例如,setInternalFilter只是调用它。

- (void) setInternalFilterTerms : (NSArray*) filterTerms {

    [self resetArray: &_internalFilters withNewData:filterTerms];
}

resetArray的定义,只是转储现有的(释放它),并复制新数据。

- (void) resetArray: (NSMutableArray**) oldArray withNewData : (NSArray*) newData {

    if (*oldArray != nil) {
        [*oldArray release];
    }


    NSMutableArray* newArray = [[NSMutableArray alloc] initWithArray:newData copyItems:YES];
    *oldArray = [newArray retain];
    [newArray release];    

}

但我的问题是我在重置方法中崩溃了。不在模拟器中,仅在设备上。

Thread 0 Crashed:
0   libsystem_kernel.dylib          0x331a3a1c __pthread_kill + 8
1   libsystem_c.dylib               0x3404c3b4 pthread_kill + 52
2   libsystem_c.dylib               0x34044bf8 abort + 72
3   libstdc++.6.dylib               0x30e4fa64 __gnu_cxx::__verbose_terminate_handler() + 376
4   libobjc.A.dylib                 0x30fda06c _objc_terminate + 104
5   libstdc++.6.dylib               0x30e4de36 __cxxabiv1::__terminate(void (*)()) + 46
6   libstdc++.6.dylib               0x30e4de8a std::terminate() + 10
7   libstdc++.6.dylib               0x30e4df5a __cxa_throw + 78
8   libobjc.A.dylib                 0x30fd8c84 objc_exception_throw + 64
9   CoreFoundation                  0x33e5f1b8 -[NSObject(NSObject) doesNotRecognizeSelector:] + 96
10  CoreFoundation                  0x33e5e642 ___forwarding___ + 502
11  CoreFoundation                  0x33dd5178 _CF_forwarding_prep_0 + 40
12  CoreFoundation                  0x33dcb156 -[NSArray initWithArray:range:copyItems:] + 366
13  CoreFoundation                  0x33dcafce -[NSArray initWithArray:copyItems:] + 54
14  Wine DB 1.1                     0x001b6a2a -[SortFilterController resetArray:withNewData:] (SortFilterController.m:1310)
15  Wine DB 1.1                     0x001b4188 -[SortFilterController setInternalFilterTerms:] (SortFilterController.m:733)

我正在使用iOS 5.0 GM种子运行xcode 4.2。我的设备仍在运行4.1.3。但那不应该有所作为吗?错误是“doesNotRecognizeSelector”。这有多奇怪。

感谢。

2 个答案:

答案 0 :(得分:1)

检查oldArray == newData。您会注意到Objective-C中的set操作的默认习惯用语是:

-(void) setFoo:(NSThing *)newThing
{
    [newThing retain];
    [thing release];
    thing = newThing;
}

如果newThing == thing,你删除了当前的东西,那么你很可能会让它调用它的析构函数。所以你总是先保留。

因此,您可以释放要复制的对象。而且,使用最新和最好的垃圾收集器,设备可能比模拟器更快地清理。两个平台上都存在错误,但内存管理器的不确定性使您认为它是瞬态的。

如果没有别的,请检查您的代码以确保您没有发布稍后在函数中使用的对象。仅仅因为变量名称不同,并不意味着它们不是同一个对象。

答案 1 :(得分:0)

是否存在于数组中的对象不符合NSCopying协议?因此,当初始化程序试图在它们上调用copy方法时,它们只是不知道如何处理它?<​​/ p>