为什么这种三元运算会导致内存增长

时间:2014-04-13 20:00:13

标签: objective-c automatic-ref-counting

在使用分配工具的标记生成功能进行测试时,以下行会导致内存增长(没有版本,只有一个malloc线在仪器中)

- (instancetype)initWithTitle:(NSString *)title andImageNamed:(NSString *)imageName andButtonProperties:(NOZSKButtonNodeProperties *)buttonProperties
{
   ...
    textNode.text = buttonProperties.buttonTitleIsUppercase ? 
        [title uppercaseStringWithLocale:[NSLocale currentLocale] ] :  title;
   ...
}

以下是调用它的代码

NOZSKButtonNodeProperties *props = [self getThreeButtonProps];
...
props.buttonTitleIsUppercase = YES;
...

// this initializer is calling the above initializer by passing nil for imageName arg
NOZSKButtonNode *btn = [[NOZSKButtonNode alloc] initWithTitle:@"Play Again" andButtonProperties:props];

3 个答案:

答案 0 :(得分:1)

-uppercaseStringWithLocale:制作title字符串的大写副本。这需要分配。虽然你没有表明这一点,但我认为textNode都保留了text属性,并且范围比-initWithTitle:andImageNamed:andButtonProperties:方法更宽,因此继续生效。

答案 1 :(得分:1)

如果没有更完整的代码,则无法确定,但如果有帮助,可以猜测。

听起来你可能正在追逐鬼魂。您是否看到由于此代码跨越运行循环的不同迭代而增加内存?

说明:即使使用ARC,一些内存也会放在“自动释放池”中,而不是在不再需要时立即释放。这是MRC遗留下来的遗憾。 ARC能够避免使用自动释放池并更快地释放内存,但不能全部使用。

自动释放池通常在主运行循环的每次迭代中清空一次。如果分配并释放大量内存以响应单个事件(例如在长循环中),将有问题的代码包装在@autorelease { ... }块中并创建并在退出时清空本地自动释放是值得的。池。这有助于降低峰值内存使用率 - 它不会释放更多内存,只是更快地清理它。

当您更改代码并看到明显的改进时,您可能只是以更适合ARC优化的方式重新组织代码,这样可以减少自动释放池的使用,因此可以更快地释放内存。

如果(a)内存在多个事件中增加或(b)您使用的峰值内存过高,则只需要关注。在ARC(a)下应该是罕见的,而(b)需要找到源并将其包装在@autorelease { ... }块中。

HTH

答案 2 :(得分:0)

textNode.text = buttonProperties.buttonTitleIsUppercase ? 
    [title uppercaseStringWithLocale:[NSLocale currentLocale] ] :  title;

当您编写[title uppercaseStringWithLocale:]时,此方法必须创建一个新实例,以便将给定字符串更改为大写。这将增加程序的内存使用量,因为必须分配这个新字符串 此外,它有助于了解您是否使用ARC,因为我不认为这应该是ARC的问题。