AVCam内存不足警告
这与其说是一个问题,不如说是我在 Apple 提供的用于 iOS4 和 5 相机操作的 AVCam 示例代码中发现的内容的记录。对我来说,问题的症状是我的应用程序在拍摄大约 5-10 张照片后启动 AVCamViewController 时会崩溃。
我通过内存泄漏分析器运行该应用程序,没有明显的泄漏,但在使用活动监视器进行检查时,我发现每次启动相机时,称为 mediaserverd 的东西都会增加 17Mb,当它达到 ~100Mb 时,应用程序崩溃并出现多个低值内存警告。
This is less a question and more a record of what I've found around the AVCam sample code provided by Apple for iOS4 and 5 camera manipulation. The symptoms of the problem for me were that my app would crash on launching the AVCamViewController after taking around 5-10 photos.
I ran the app through the memory leak profiler and there were no apparent leaks but on inspection with the Activity Monitor I discovered that something called mediaserverd was increasing by 17Mb every time the camera was launched and when it reached ~100Mb the app crashed with multiple low memory warnings.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我做的第一件事是将日志记录到所有 AVCam 文件的 dealloc 方法中。我很快发现 AVCamCaptureManager 和 AVCamRecorder 没有在 AVCamViewController 被释放时被释放。我检查了保留和释放调用,它们似乎是平衡的,因此我在 [captureManager release] 上放置了一个断点,发现释放后它的保留计数为 2(因此 AVCamCaptureManager dealloc 没有被调用)。
接下来,我逐步完成了捕获管理器的创建过程,发现在调用 init 方法后,它的保留计数立即为 3。
单步执行 init 方法并检查每一行的保留计数,我发现以下两行都在增加保留计数:
仔细查看,我发现removeObserver对应项位于 AVCamCaptureManager 的 dealloc 方法内(未调用该方法)因此保留计数永远不会降至 0。
为了解决这个问题,我创建了一个新的公共 removeObservers 方法:
并从 AVCamCaptureManager dealloc 方法中取出相同的行。
调用[captureManagerremoveObservers];然后调用 [captureManager release];在 AVCamViewController dealloc 方法中,成功地将保留计数降至 0。
现在使用活动监视器进行测试,mediaserverd 进程仅占用 5-17Mb,并且崩溃停止了!
希望这可以帮助其他遇到此问题的人!
First thing I did was put logging into the dealloc methods of all the AVCam files. I quickly discovered that the AVCamCaptureManager and AVCamRecorder weren't being deallocated when the AVCamViewController was. I checked out the retain and release calls and they appeared to balance so I put a breakpoint on the [captureManager release] and discovered that it had a retainCount of 2 AFTER the release (and hence the AVCamCaptureManager dealloc wasn't being called).
Next I stepped through the creation process for the capture manager and discovered that it had a retain count of 3 immediately after the init method was called.
Stepping through the init method and checking the retain count on every line I discovered the following two lines were both incrementing the retain count:
Looking through I found that the removeObserver counterparts were INSIDE the dealloc method of the AVCamCaptureManager (which wasn't being called) and so the retain count never dropped to 0.
To fix it I created a new public removeObservers method:
and taking the same lines OUT of the AVCamCaptureManager dealloc method.
Calling [captureManager removeObservers]; and THEN calling [captureManager release]; in the AVCamViewController dealloc method successfully drops the retain count to 0.
Testing with the Activity Monitor now has the mediaserverd process humming at only 5-17Mb and the crashing stops!
Hope this helps anyone else having this problem!
Apple 于 2013 年 10 月 17 日修改了示例代码,修复了保留周期。该问题是由于在
init
中定义的块中不正确使用self
造成的。这是修订说明
但是,他们引入的修复仅适用于手动保留计数的情况。如果您在项目中使用 ARC,除了摆脱
release
/retain
调用和其他明显的事情之外,weakSelf
的存储限定符还具有从__block
更改为__weak
,如下所示。事实上,
__block
的语义随着 ARC 的改变而改变。在 MRC 中,它会导致变量被弱引用,而在 ARC 中则不会,因此必须使用 __weak 来实现此目的。有关此主题的更多信息可以在此处找到:在实现 API 时,如何避免在块中捕获 self?
使用最新版本中的新
init
实现并使用__weak
而不是__block
,最后导致正确调用dealloc
方法。最后,对于那些讨厌携带旧遗留代码的人,这里有一个
AVCam
项目的现代化版本:https://github.com/Gabro/AVCam功能:
Apple revised the sample code on Oct 17 2013, fixing the retain cycle. The issue is due to a improper usage of
self
within the blocks defined in theinit
.Here's the revision description
However, the fix they introduced only works in case of Manual Retain Count. If you are using ARC on the project, apart from getting rid of
release
/retain
calls and other obvious things, the storage qualifier forweakSelf
has to be changed from__block
to__weak
, like follows.In fact the semantic of
__block
changed with ARC. In MRC it caused the variable to be weakly referenced, wheres in ARC it does not and__weak
must be used for this purpose.More information about this topic can be found here: How do I avoid capturing self in blocks when implementing an API?
Using the new
init
implementation from the last revision and using__weak
instead of__block
, finally caused thedealloc
method to be properly called.Finally, for those who hate to carry around old legacy code, here's a modernized version of the
AVCam
project: https://github.com/Gabro/AVCamFeatures:
最近遇到这个问题。我发现真正的根本问题是 deviceConnectedBlock 和 deviceDisconnectedBlock 隐式引用 self,导致循环引用。要修复此问题,请将这些块中的所有 ivar 引用更改为使用weakSelf。
这样,您就不需要记住显式调用拆卸方法。
希望这对其他人有帮助。
REF: 使用 NSNotificationCenter 时未调用视图控制器 dealloc带有ARC的代码块方法
Ran into this problem recently. I found that the real root problem was that deviceConnectedBlock and deviceDisconnectedBlock were implicitly referring to self, leading to retain cycles. To fix it, change all the ivar references in those blocks to use weakSelf.
This way, you won't need to remember to call a teardown method explicitly.
Hope this helps someone else.
REF: View controller dealloc not called when using NSNotificationCenter code block method with ARC