内存问题

我正在编写一个库,使用AVFoundation将资产导出到一个文件。 我创build一个阅读器,一个编写器,将input和输出连接到这些input和输出,然后调用input上的requestMediaDataWhenReadyOnQueue方法来开始提取数据。 提供给这个方法的块callback看起来有点像这样:

 [input requestMediaDataWhenReadyOnQueue:queue usingBlock:^{ while ([input isReadyForMoreMediaData]) { CMSampleBufferRef buffer; // The track has some more data for us if ([reader status] == AVAssetReaderStatusReading && (buffer = [output copyNextSampleBuffer])) { BOOL result = [input appendSampleBuffer:buffer]; CFRelease(buffer); if (!result) { // handle error break; } // The track is finished, for whatever reason } else { [input markAsFinished]; ⬅ switch ([reader status]) { // inspect the status and act accordingly } } } }]; 

这适用于iOS 5,但在iOS 4上,代码在用⬅箭头标记的行之后死于EXC_BAD_ACCESS。 经过一番探索之后,我觉得在标记input完成后立即销毁该块。 在执行坏行之前,完全有效的self指针变成0xfff…或debugging器报告的一些垃圾值。 但是前面指出的对象很好,就像僵尸工具所证实的那样,它不会被释放。

我错过了什么?

看到相同(类似)的问题。 iOS5开心,iOS4.3.5,不开心。 有兴趣了解你最终find什么。

通过在requestMedatWhenReadyOnQueue块之前显式地保留写入器,写入器input,阅读器,阅读器输出并在else子句的最后明确地释放全部四个来实现它。

该文件确实说,标记完成后,“块应该退出”。 也许他们不是在开玩笑吧。 如果除了退出以外的任何事情,这是一个错误。 上述解决方法似乎工作。

更新:我仍然发现,即使在保留和释放所有资产对象后,它偶尔也会崩溃。 正如你的问题所观察到的那样,在标记写入器input完成之后,它很快崩溃,就好像这个块本身被解除分配。 作为函数的一部分而不是仅仅传递块。 我创build一个复制的块属性是一个长寿命对象的一部分。 我用Block_copy初始化它,只在长寿命对象的析构函数中释放它。 这似乎是诀窍。 从那以后,我还没有看到4.3.5的崩溃。

尝试[self retain]作为块的第一行,[self release]作为最后一行。

另一个关键问题是,如果使用requestMediaDataWhenReadyOnQueue挂起App(进入后台),则需要显式覆盖所有[reader status]值,因为应用程序重新启动时将失败。 在某些情况下,我发现该块运行失败状态标志不止一次。 在其他具有类似代码的文章中,有很多[保留] AVvariables,然后在块的末尾释放。 因为该块可以运行多次,所以在应用程序进入后台状态的情况下,此方法不起作用。

我发现以下在“开关”(上面)中工作良好:

  case AVAssetReaderStatusReading: break; case AVAssetReaderStatusCompleted: [videoWriterInput markAsFinished]; //do something else, like add an audio stream [videoWriter finishWriting]; break; case AVAssetReaderStatusFailed: [videoWriterInput markAsFinished]; [videoWriter finishWriting]; break; case AVAssetReaderStatusCancelled: case AVAssetReaderStatusUnknown: [videoWriterInput markAsFinished]; [videoWriter cancelWriting]; break; } dispatch_sync(dispatch_get_main_queue(), ^{ //hide any progress indicators }); break; 

除了“自我”以外,没有任何东西被保留。 如果需要,块应该自动保留variables。