【问题标题】:CATextLayer memory residue after deallocation释放后的 CATextLayer 内存残留
【发布时间】:2011-03-06 12:00:36
【问题描述】:

我最近才进入 iPhone 开发领域,但我仍在摸索中。在测试各种 CALayer 和 CATextLayer 行为时,我偶然发现了一些有趣的东西。

我创建了一个 iPhone 测试应用,它的视图中只有 2 个 UIButton。其中一个分别调用“allocateAutoReleasedLayers”函数和另一个“deallocateAutoReleasedLayers”。以下代码sn-ps代表函数体。

-(IBAction)allocateAutoReleasedLayers:(id)sender
{
    for ( int i = 0; i < 500; ++i )
    {
        CALayer * layer = [ CALayer layer ];
        [ master addSublayer: layer ];
    }
}

-(IBAction)deallocateAutoReleasedLayers:(id)sender
{
    master.sublayers = nil;
}

现在,测试的目的是了解 iOS 如何处理层自动释放。当使用“分配”分析器运行时,应用程序占用 646.452 字节的内存。在我点击“分配”按钮后,内存使用量上升到 719.228 字节来托管所有创建的 500 个空层,这没关系,因为当我点击“解除分配”按钮时,使用的内存回落到 656.732 字节(我猜想分配前和释放后使用的内存不匹配是 iOS 内部内存管理的结果。

有趣的部分发生在我将“分配”过程的一部分更改为创建 CATextLayers 而不是 CALayers 时。

-(IBAction)allocateAutoReleasedLayers:(id)sender
{
    for ( int i = 0; i < 500; ++i )
    {
        NSString * layerString = [ [NSString alloc ] initWithFormat: @"1231" ];
        CATextLayer * textLayer = [ CATextLayer layer ];
        [ textLayer setString: layerString ];
        [ textLayer setFrame: CGRectMake( 0, 0, 100, 200) ];
        [ textLayer setFont: @"Helvetica-Bold" ];
        [ textLayer setFontSize: 20 ];
        [ master addSublayer: textLayer ];
        [ layerString release ];
    }
}

应用程序在分配之前从通常的 651.868 字节使用量开始,然后上升到使用的 2.13MB(我猜 CATextLayers 的内存使用量相当大),在解除分配时,内存回落到 950.372 字节。

现在,我的问题如下:在处理 CATextLayers 时,在分配之前和释放之后发生了哪些 300kB 差异的原因。我想我对 iOS 管理内存方式的误解可能是原因,但我使用的创建 CATextLayer 的方式与创建 CALayer 时使用的方式完全相同。

提前致谢并致以最诚挚的问候!

【问题讨论】:

    标签: iphone objective-c ios memory calayer


    【解决方案1】:

    我已经在模拟器上运行了您的代码,但看不到这种行为。以下是我执行的步骤:

    1) 在“分配”工具下运行应用程序。
    2) 等到它完全启动。
    3) 标记堆 -> 堆(0)
    4) a) 使用allocateAutoReleasedLayers: 分配CATextLayer 实例 b) 使用deallocateAutoReleasedLayers: 解除分配 c) 标记堆 -> 堆(1)

    操作 4 给了我们一个测试模式(Allocate-Deallocate-Mark heap),所以

    5) ADM(2) -> 堆(2)
    6) ADM(3) -> 堆(3)
    7) ADM(4) -> 堆(4)
    ...

    Heap(n) 和 Heap(n-1) 之间的差异在执行 ADM(n) 时约为 2K,而在执行 ADM(n+1) 时下降到 0.5-1k(这可能是因为框架重新创建了一些东西并发布旧版本,例如,我可以注意到 CGDataProvider)。无论如何,Heap(n+1)-Heap(n) 中的东西包含一些不相关的东西,比如 CSEvent、UITouchData 等,它们很可能被分配用于处理按钮点击。

    您是在设备还是模拟器上进行测试?您重复此 ADM 循环多少次?后续堆之间的差异内容是什么?这很有趣,因为 300k 对我来说似乎太多了。

    【讨论】:

    • 我一直在实际设备 iPhone 3G - iOS v4.1 上进行测试。 'ADM' 循环已经调用了大约 7-8 次,老实说,我不知道 Allocations 能够巧妙地显示内存使用量的差异,在堆镜头之间,更不用说隔离负责获取的对象了它。仅在该领域,您就提供了很多帮助:) 我已经确定内存分配来自“CGFontCopyTableForTag”,并尝试通过使用“CGFontCreateWithFontName”和“CGFontRelease”分配和取消分配表来解决问题,但问题是仍然存在。
    • 您是否在其他地方调用所有这些函数(CGFontCopyTableForTag 等)?我在上面的 sn-ps 中看不到它们。
    • 不,上面的代码sn-ps是测试项目中99%的代码。另外 1% 是包含声明的头文件。我猜有问题的函数是由 '[ textLayer setFont: @"Helvetica-Bold" ];' 调用的。初始化字体。我现在正在工作,所以我无法测试代码,因为我们在 Windows 上,但我一回到家就会去。感谢您花时间调试问题顺便说一句:) 我会尝试不定义特定字体,也许 iOS 会使用它在内存中找到的字体、系统字体或其他东西。
    • 我已经在 iPhone 4 & iPad 4 (iOS 4.2.1) 上测试过了。与以前相同的结果(差异中的 1-6KB 对象大部分在下一次迭代中重用)。现在它变得有趣了。尝试使用这个项目进行测试,可能是配置问题 - git://github.com/hoha/test_catextlayer_leaks.git
    • 我已经尝试了您的项目,当我将[self.view.layer addSublayer: master]; 添加到-(void)viewDidLoad 过程的末尾时,我得到了相同的结果。我添加后面的原因是相反,CATextLayers 不会自然地出现在屏幕上,因为master 图层尚未分配给视图中的图层。 Heap(1)-Heap(Baseline) 包含 280KB 的内存增加,所有后续的 heapshots 都增加了接近 10KB 的量。这个
    猜你喜欢
    • 2021-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    • 1970-01-01
    • 2012-12-06
    • 1970-01-01
    • 2014-09-20
    相关资源
    最近更新 更多