1

我正在编写 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)在代码中,程序将停止 - 没有显示错误 - 它只是崩溃。如果我注释掉该行,我当然会遇到内存问题,并且代码在收到“收到内存警告”后大约在第四首歌曲崩溃。

我究竟做错了什么?

4

2 回答 2

1

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

当您最终调用 CFRelease 时,您是在一个刚刚检查为 NULL 的变量上调用它。根据这个 StackOverflow 答案,在 NULL 上调用 CFRelease 是不安全的,所以这就是你崩溃的原因:

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

CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];

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

如果这不能解决您的崩溃问题(即使解决了),请尝试在您的代码上运行静态分析器(在 Xcode 的产品菜单中选择“分析”)并查看它是否报告任何潜在的泄漏或过度发布。请记住,您收到的每个黄色和蓝色警告都是潜在的崩溃,因此请尝试将它们全部修复。

编辑:我突然想到你的循环没有多大意义——你为什么一遍又一遍地阅读样本然后把它们扔掉?您是否可能在您的 while 循环中弄错了 NULL 检查,而您实际上是打算写这个?

CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];

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

CFRelease(sample);

这也应该没问题,因为在这种情况下,您在释放样本之前明确检查样本不为 NULL。尽管在对样本进行任何操作之前您仍然会丢弃样本,并且如果 readerOutput 不包含样本,您也会冒无限循环的风险。

于 2012-01-06T00:35:16.950 回答
0

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

于 2012-01-04T19:44:29.453 回答