尴尬:带有Array的encodeObject导致EXC_BAD_ACCESS错误,绝望

时间:2009-12-29 00:04:41

标签: iphone objective-c

我有一个符合NSCoding的自定义对象,因为该对象在终止时应该可写入磁盘。在这个类中,我有各种属性,包含Cocoa对象类型,如NSStrings,NSArrays,NSDictionaries。一个特殊属性是这个:

@property (readwrite, copy) NSArray  *artistReleases;

它实际上是一个应该容纳一些NSDictionaries的数组。这些字典是在一个类方法中创建的,该方法负责解析XML文件中的数据。

artist.artistReleases = [NSArray arrayWithArray:releases];

当我尝试使用编码器保存属性时发生错误:

[encoder encodeObject:artistReleases forKey:@"artistReleases"];

我会收到EXC_BAD_ACCESS错误。 NSZombie告诉我

*** -[CFString retain]: message sent to deallocated instance 0xd6f28fe0

......我绝对不知道在哪里寻找这种保留。 malloc_history告诉我:

ALLOC 0xd6f28fe0-0xd6f28fff [size=32]: thread_b0244000 |thread_start | 
_pthread_start | __NSThread__main__ | -[NSThread main] | 
-[SearchViewController invokeGetArtist:] | +[GetDetails getArtist:summary:theURL:] |
-[CXMLNode stringValue] | +[NSString stringWithUTF8String:]   | 
-[NSPlaceholderString initWithBytes:length:encoding:] | 
CFStringCreateWithBytes | __CFStringCreateImmutableFunnel3 |
_CFRuntimeCreateInstance | GMmalloc_zone_malloc_internal 

我不清楚该怎么做。这对我没有任何意义。也许有人可以通过解释malloc历史来指出我在某个方向。


修改

这是填充有问题的属性的部分。为了修复错误,我对一些CXMLNode调用进行了评论,并没有在这里插入。这也意味着似乎没有错误连接到这些对象(直到我尝试访问使用这些方法创建的数据)。顺便说一句,我使用TouchXML进行XPath查询。

NSArray *releaseNodes;
releaseNodes = [root nodesForXPath:@"/pathToReleases" error:nil];
NSMutableArray *releases = [[NSMutableArray alloc] init];

for (CXMLElement *resultElement in releaseNodes) {
    if (resultElement != nil) {
        NSMutableDictionary *releaseElement = [[NSMutableDictionary alloc] init];

        for (int counter = 0; counter < [resultElement childCount]; counter++) {
            [releaseElement setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];
        }
        [releases addObject:releaseElement];
        [releaseElement release];
    }
}
if ([releases count] == 0) 
    [releases addObject:[NSMutableDictionary dictionaryWithObject:@"-" forKey:@"title"]];
artist.artistReleases = [NSArray arrayWithArray:releases];

编辑2 我已经缩小了有关财产失去其内容的地方。通过gdb在某个点之后对该属性进行修改会导致错误

Program received signal SIGTRAP, Trace/breakpoint trap.

这一点是为getArtist调用而创建的自动释放池被释放的地方。所有其他属性都很好,但是......所以 - 毕竟错误在于我在第一次编辑中发布的代码部分?

2 个答案:

答案 0 :(得分:1)

你的GetDetails课程都是borked或任何正在调用它的人都是borked。具体来说,请参阅分配跟踪的这一部分:

+[GetDetails getArtist:summary:theURL:]
-[CXMLNode stringValue]

如果正确实现,CXMLNode的{​​{1}}方法将返回一个自动释放的字符串。需要在其上调用stringValue(直接或通过属性设置器)。

或者,-retain方法可能会返回一个保留的字符串?如果是这样,那么它应该在返回之前返回getArtist:summary:theURL:的结果。

没有看到更多代码,就不可能多说。如果我是下注类型,我怀疑stringValue是通过引用返回艺术家和摘要?如果是这样,那就是一个强大的愚蠢设计 - 非典型的,甚至 - 但是我敢打赌,来电者假设艺术家和/或摘要在他们不是时保留? ....或者在某个地方有一个额外的自动呼叫?

答案 1 :(得分:0)

找出填充数组的位置。最有可能的是,您已经过度释放了已插入阵列中的一个字符串。当编码器对象尝试访问过度释放的对象时,您会收到错误。