程序在Xcode中崩溃,没有显示错误

时间:2012-01-04 19:01:09

标签: iphone memory-management avassetreader

我正在编写iPhone应用程序,并且在内存方面存在一些问题。以下是代码:

NSURL *url = [curItem valueForProperty: MPMediaItemPropertyAssetURL];

AVURLAsset *asset = [AVURLAsset URLAssetWithURL: url options:nil];

NSError *error = nil;

AVAssetReader* reader = [[AVAssetReader alloc] initWithAsset:asset error:&error];

AVAssetTrack* track = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];

NSMutableDictionary* audioReadSettings = [NSMutableDictionary dictionary];
[audioReadSettings setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM]
                     forKey:AVFormatIDKey];

AVAssetReaderTrackOutput* readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track outputSettings:audioReadSettings];

[reader addOutput:readerOutput];

[reader startReading];

CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];

while( sample != NULL)
{
    sample = [readerOutput copyNextSampleBuffer];

}
CFRelease(sample);

我正在阅读用户iTunes资料库中的歌曲(curItem是当前歌曲),如果我在代码中留下最后一行:CFRelease(sample),程序将停止 - 没有显示错误 - 它只是崩溃。如果我注释掉这一行,我当然会遇到内存问题,并且在收到“收到内存警告”之后代码就第四首歌崩溃了。

我做错了什么?

2 个答案:

答案 0 :(得分:1)

命名约定copyNextSampleBuffer意味着您拥有返回的对象,因此您可以正确释放它,但是您在循环中多次调用copyNextSampleBuffer方法并覆盖以前的副本而不释放它。

当你最终调用CFRelease时,你在一个刚刚检查过的变量上调用它。根据{{​​3}},在NULL上调用CFRelease是不安全的,这就是你崩溃的原因:

您需要做的是在覆盖变量之前在while循环中调用release,如下所示:

CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];

while( sample != NULL)
{
    CFRelease(sample);
    sample = [readerOutput copyNextSampleBuffer];
}

如果这不能解决您的崩溃问题(即使确实如此),请尝试在您的代码上运行静态分析器(在Xcode的产品菜单中选择Analyze),看看它是否报告任何潜在的泄漏或超过版本。请记住,你得到的每一个黄色和蓝色警告都是潜在的崩溃,所以试着解决它们。

编辑:我觉得你的循环没有多大意义 - 你为什么一遍又一遍地读取样本然后把它们扔掉?您是否在while循环中得到了NULL检查错误,而您实际上是想写这个呢?

CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];

while( sample == NULL)
{
    sample = [readerOutput copyNextSampleBuffer];
}

CFRelease(sample);

这也应该没问题,因为在这种情况下,您在释放之前明确检查样本是否为NULL。虽然你在做任何事情之前仍然丢弃了样本,但如果readerOutput不包含样本,你也冒着无限循环的风险。

答案 1 :(得分:0)

使用autorelease或ARC来摆脱“过早发布的综合症”。在这两种情况下,发布任务都由其他人管理。对于一个新项目,我建议使用ARC。