我正在学习内存管理在Objective-C中的工作方式。据我了解,标记为autorelease
的对象将添加到封闭的NSAutoreleasePool
中,并在释放/排空池时释放。
为了尝试新知识,我创建了一些测试;创建100万个对象需要约17mb,创建相同的对象但立即释放它们则需要约1mb。但是,我无法使NSAutoreleasePool
正常工作,使用下面的代码仍然使用〜17mb,我不明白为什么。
#include <objc/objc-runtime.h>
#include <stdio.h>
int main(void) {
Class NSAutoreleasePool = objc_getClass("NSAutoreleasePool");
Class Object = objc_getClass("NSObject");
SEL new = sel_registerName("new");
SEL drain = sel_registerName("drain");
SEL autorelease = sel_registerName("autorelease");
id pool = objc_msgSend(NSAutoreleasePool, new);
for (int i = 0; i < 1e6; i++) {
id obj = objc_msgSend(Object, new);
objc_msgSend(obj, autorelease);
}
objc_msgSend(pool, drain);
printf("OK\n");
getchar();
return 0;
}
答案 0 :(得分:4)
在release
制作后立即每个对象,从未有多于一个的对象存在于一个时间。因此,运行时可以为每个新对象回收相同的内存。运行时只需要向操作系统请求足够的内存来容纳该对象。
在autorelease
创建后的每个对象,每个对象的生命,直到自动释放池被排出,所以你最终同时存在百万对象。运行时必须要求操作系统有足够的内存来容纳所有对象。而且由于运行时无法预先知道要创建多少个对象,因此它会向操作系统递增地请求内存块。也许它要求1 MIB,并且当该1 MIB耗尽,它要求另一个1 MIB,等等。
通常,当你的程序释放一些存储器(在这种情况下,因为它破坏的对象),则运行时不会内存返回到操作系统。它使内存保持可用状态,以便下次创建对象时可以重复使用。
操作系统知道它已为您的进程分配了多少内存,但不知道该内存的哪些部分(在进程内)被视为“正在使用”,哪些部分被视为“空闲”。
活动监视器和top
都向操作系统询问有关您的过程的信息。因此他们只知道操作系统知道什么,即已为您的进程分配了多少内存。他们不知道有多少内存正在使用,有多少空闲。
如果你想要多少内存是在你的程序活动对象使用一个更准确的图片,你需要使用一个更具侵入性的工具。该仪器的程序,其自带的Xcode,可以告诉你多少内存在使用中通过“实时分配”使用分配的工具。
下面就是该分配仪器显示,当我运行在它之下你的程序约三秒钟:
因此您可以看到分配工具检测到总共1,001,983个“暂态”分配。瞬时分配是在仪器停止记录之前分配并释放的一块内存。
您还可以看到分配的“持久”字节(是分配的内存,并且在仪器停止记录时未释放)为506 KiB,但是分配的总字节(包括以后释放的字节)为23.5 MiB。 p>