为什么使用[NSDate date]时ARC无法释放内存,但是使用[[NSDate alloc] init]却可以正常工作? [英] Why doesn't ARC free memory when using [NSDate date] but works fine using [[NSDate alloc] init]?

查看:112
本文介绍了为什么使用[NSDate date]时ARC无法释放内存,但是使用[[NSDate alloc] init]却可以正常工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一些Objective-C应用程序,除了不断增长的内存占用外,它似乎运行良好.我在最新版本的Xcode 4.6.2下使用ARC.我的系统是10.7.5.

I've written some Objective-C application that seems to work fine, except for an ever-growing memory footprint. I'm using ARC under the last version of Xcode 4.6.2. My system is 10.7.5.

我对Objective-C还是很陌生,需要一些帮助来弄清楚内存的状况.我将问题的范围缩小到解释以下基本代码的行为为何如此.

I'm very new to Objective-C and need some help figuring out what's going on with my memory. I've narrowed down the problem to explaining why the following basic piece of code behaves like it does.

此代码已添加到Xcode提供的基于香草可可的应用程序模板中(启用了ARC).

This code is added in the vanilla Cocoa-based application template that Xcode gives (ARC enabled).

案例A

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
    NSDate* d;
    for(int i=0; i<1000000; i++){
        d = [[NSDate alloc] init];
    }
}

一切都按预期进行,ARC回收了运行中的内存.即,存储器使用历史非常平坦.当for循环结束时,该应用程序将占用大约25MB的内存.

Everything goes as expected, ARC reclaims the memory on the fly. Namely, the memory usage history is very flat. When the for loop ends, the app takes about 25MB memory.

案例B

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
    NSDate* d;
    for(int i=0; i<1000000; i++){
        d = [NSDate date];
    }
}

这对我来说真的很神秘.刚运行该应用程序时,(实际)内存使用量会一直增加到约53MB,然后一直保持在那里.

Here things are really mysterious to me. When just running the app, the (real) memory usage keeps increasing to about 53MB and then stays there, forever.

但是,运行分配分析器工具时,我可以看到在for循环结束时,所有对象都被释放了,非常类似于自动释放池所期望的那样.另外,用@autoreleasepool {}封闭for循环的主体,使情况B的行为与情况A相同(如预期的那样).

However, when running the allocations profiler tool, I can see that at the end of the for loop, all the objects are deallocated, very much like you would expect with an autorelease pool. Also, enclosing the body of the for loop with an @autoreleasepool{} makes case B behave like case A (as expected).

所以,三个问题:

  1. 在ARC中,使用自动释放" [NSDate date]和alloc初始化对象有什么区别? (我认为这里其他问题几乎没有.)
  2. 为什么运行代码时ARC似乎不起作用?
  3. 为什么配置文件应用程序和实际应用程序的内存行为有所不同?
  1. Under ARC, what is the difference between using the "autoreleased" [NSDate date] and the alloc init object? (I thought there would be close to none from other questions here.)
  2. Why doesn't ARC seem to kick in when running the code?
  3. Why is there a difference in the memory behavior of the profiled application and the actual application?

推荐答案

最终会释放自动释放对象,而在alloc/init情况下,一旦不再使用它们就会释放它们.

Autorelease objects are released eventually, whereas in the alloc/init case they are released as soon as they're not used anymore.

此行为会导致对象在自动循环释放以便稍后释放的情况下,在整个循环中都保留在内存中,而如果您alloc/init它们,则会发送release方法循环体内.

This behavior causes your objects to persist in memory for the whole loop in case they are autoreleased for the being released later on, whereas if you alloc/init them, a release method is sent within the loop body.

通过将其包装在@autoreleasepool中,可以很容易地使主体循环的存储效率提高,如下所示:

You can easily make the body loop memory-efficient by wrapping it in a @autoreleasepool like follows:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
    @autoreleasepool {
        NSDate* d;
        for(int i=0; i<1000000; i++){
            d = [NSDate date];
        }
    }
}

这将给ARC一个提示,表明您希望在每次循环迭代时创建并释放自动释放池.

This will give a hint to ARC, signaling that you want to create and release an autorelease pool at every loop iteration.

在特定情况下,最简单的选择可能是使用alloc/init方法,以使编译器自动执行正确的操作,但是如果您的循环体中有许多返回自动释放的工厂方法实例中,@autoreleasepool块可能是一个不错的选择.

In the specific case the easiest option would probably be to use alloc/init methods, in order for the compiler to do the right thing automatically, but if you have a loop body with many factory methods that return autoreleased instances, the @autoreleasepool block is probably a great way to go.

最后,@autoreleasepool不是ARC专有的.它自LLVM 3.0起就存在,并且具有足够的现代目标(即iOS5和OSX 10.7),它的速度比老式的NSAutoreleasePool要快得多.

As a final remark, @autoreleasepool is not an ARC exclusive. It used to exist since LLVM 3.0 it, and with sufficient modern targets (namely iOS5 and OSX 10.7 on) it's known to be much faster than the old-fashioned NSAutoreleasePool.

这篇关于为什么使用[NSDate date]时ARC无法释放内存,但是使用[[NSDate alloc] init]却可以正常工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆