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

时间:2021-05-20 23:08:02

I have a retain/release project that has a simple algorithm. I start out w/ a 100000 objects mutable array and every 5 seconds interval I remove 1000 objects at the beginning and add 1000 objects at the end. In theory my memory footprint should stay the same after a lil delay, however it consistently rises until it caps out at a certain amount. But removing all its objects with "[array removeAllObjects]" and releasing the array doesn't reclaim all the memory back, just a portion. I am running in release scheme, with no debugger, and using the activity monitor to track memory usage.

我有一个保留/发布项目,有一个简单的算法。我开始用一个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 个解决方案

#1


3  

Monitoring your memory usage with Activity Monitor is pretty unreliable. First, which memory field are you watching (Virtual Private Memory, Real Private Memory, Real Shared Memory, or Real Memory)?

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

Second, when your code makes an allocation request, that typically goes, directly or indirectly, to the malloc routines. The malloc routines try to satisfy your request from the memory that it already has. If it can't then it requests more from the system. When you free memory, it goes back to malloc. Malloc does not necessarily return it to the system. It may keep it to more quickly satisfy future requests. So, you may not see your process's memory usage go down, at least not all the way, even if your program is releasing everything it allocated.

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

The proper way to check that your program is managing memory correctly is to use Instruments with the Leaks and Allocations tools.

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

#2


3  

When you create your NSURL using

使用时创建NSURL

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

You are creating an Autoreleased object. Autoreleased objects get stored in the autorelease pool and are only destroyed when that pool is emptied. The main pool is flushed every 60th of a second when the main run loop fires, so maybe your objects are being released later than you expect them to be.

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

Try wrapping your for loops in an @autoreleasepool { } block so that any autoreleased objects created inside the loop are flushed immediately, or alternatively create your NSURL using alloc/init so that it's not autoreleased, e.g.

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

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

Then see if that changes your memory usage.

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

#1


3  

Monitoring your memory usage with Activity Monitor is pretty unreliable. First, which memory field are you watching (Virtual Private Memory, Real Private Memory, Real Shared Memory, or Real Memory)?

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

Second, when your code makes an allocation request, that typically goes, directly or indirectly, to the malloc routines. The malloc routines try to satisfy your request from the memory that it already has. If it can't then it requests more from the system. When you free memory, it goes back to malloc. Malloc does not necessarily return it to the system. It may keep it to more quickly satisfy future requests. So, you may not see your process's memory usage go down, at least not all the way, even if your program is releasing everything it allocated.

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

The proper way to check that your program is managing memory correctly is to use Instruments with the Leaks and Allocations tools.

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

#2


3  

When you create your NSURL using

使用时创建NSURL

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

You are creating an Autoreleased object. Autoreleased objects get stored in the autorelease pool and are only destroyed when that pool is emptied. The main pool is flushed every 60th of a second when the main run loop fires, so maybe your objects are being released later than you expect them to be.

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

Try wrapping your for loops in an @autoreleasepool { } block so that any autoreleased objects created inside the loop are flushed immediately, or alternatively create your NSURL using alloc/init so that it's not autoreleased, e.g.

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

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

Then see if that changes your memory usage.

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