程序在 Xcode 中崩溃且未显示任何错误

发布于 2024-12-24 03:34:07 字数 1137 浏览 0 评论 0原文

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

我做错了什么?

I am in the process of writing an iPhone app, and am having a few problems with the memory. Here is the code below:

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);

I am reading songs from the user's iTunes library (curItem is the current song), and if I leave the last line: CFRelease(sample) in the code, the program will stop - no error is shown - it just crashes. If I comment out the line, I of course run into memory problems, and the code crashes on about the fourth song after getting "Received memory warning."

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浮华 2024-12-31 03:34:07

命名约定 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 不包含样本,您还会面临无限循环的风险。

The naming convention copyNextSampleBuffer implies that you own the object returned so you are correct to release it, but you are calling the copyNextSampleBuffer method multiple times in a loop and overwriting the previous copy without releasing it.

When you do finally call CFRelease, you are calling it on a variable that you have just checked to be NULL. According to this StackOverflow answer, calling CFRelease on NULL is not safe, so that's why you're crashing:

What you need to do instead is call release inside your while loop before you overwrite the variable, like this:

CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];

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

If that doesn't fix your crash (and even if it does), try running the static analyser over your code (select Analyze in the product menu in Xcode) and see if it reports any potential leaks or over-releases. Remember, every yellow and blue warning you get is a potential crash so try to fix them all.

EDIT: It just occurs to me that your loop doesn't make much sense - why are you reading samples over and over and then just throwing them away? Did you perhaps get the NULL check wrong in your while loop and you actually meant to write this instead?

CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];

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

CFRelease(sample);

That should also be fine as in that case you are explicitly checking that the sample is not NULL before releasing it. Although you're still throwing away the sample before doing anything with it, and you also risk an infinite loop if the readerOutput contains no samples.

你没皮卡萌 2024-12-31 03:34:07

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

Use either autorelease or ARC to get rid off the "too early release syndrom". In both cases the release-task is managed by someone else. For a new project I'd suggest ARC.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文