Cocoa内存问题,当从数组中删除对象时,内存不会被回收

时间:2012-04-18 21:29:26

标签: objective-c xcode macos cocoa osx-lion

我有一个具有简单算法的保留/发布项目。我开始用一个100000个对象的可变数组,每隔5秒我开始删除1000个对象,最后添加1000个对象。从理论上讲,我的记忆足迹应该在延迟一段时间后保持不变,但是它会持续上升,直到它达到一定量。但是使用“[array removeAllObjects]”删除所有对象并释放数组不会回收所有内存,只是回收一部分。我在发布方案中运行,没有调试器,并使用活动监视器来跟踪内存使用情况。

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
    array = [[NSMutableArray alloc] init];
    for(int i = 0; i<100000; i++){
        NSURL *url = [NSURL URLWithString:@"http://www.apple.com"];
        [array addObject:url];
    }
    self.t = [NSTimer scheduledTimerWithTimeInterval:10  target:self selector:@selector(addAndRemove:) userInfo:nil repeats:YES];

}

-(IBAction)addAndRemove:(id)sender{
     [array removeObjectsInRange:NSMakeRange(0, 1000)];

     for(int i = 0; i<1000; i++){
        NSURL *url = [NSURL URLWithString:@"http://www.apple.com"];
        [array addObject:url];
     }
}

-(IBAction)clear:(id)sender {
    [array removeAllObjects];    
    [array release];
    [t invalidate];
    t = nil;
}

2 个答案:

答案 0 :(得分:3)

使用

创建NSURL时
NSURL *url = [NSURL URLWithString:@"http://www.apple.com"];

您正在创建一个Autoreleased对象。自动释放的对象存储在自动释放池中,并且仅在清空该池时销毁。当主运行循环触发时,主池每60秒刷新一次,因此您的对象可能比您预期的要晚一些。

尝试在@autoreleasepool {}块中包装for循环,以便立即刷新在循环内创建的任何自动释放的对象,或者使用alloc / init创建NSURL,以便它不会自动释放,例如。

NSURL *url = [[NSURL alloc] initWithString:@"http://www.apple.com"];

然后看看是否会改变你的内存使用情况。

答案 1 :(得分:3)

使用Activity Monitor监控内存使用情况非常不可靠。首先,您正在观看哪个内存字段(虚拟专用内存,实际专用内存,实际共享内存或实内存)?

其次,当您的代码发出分配请求时,通常会直接或间接地发送到malloc例程。 malloc例程尝试从已有的内存中满足您的请求。如果它不能,那么它从系统请求更多。当你释放内存时,它会回到malloc。 Malloc不一定将其返回给系统。它可以使它更快地满足未来的要求。所以,你可能看不到你的进程的内存使用率下降,至少不是一直都没有,即使你的程序正在释放它分配的所有东西。

检查程序是否正确管理内存的正确方法是使用带有Leaks and Allocations工具的Instruments。