Objective-C memory not being freed with large arrays

I am developing a program in Cocoa, with the hopes of using the smallest amount of memory possible. To check this, I have been using Activity Monitor. My program has a fairly large NSMutableArray containing instances of NSString, and when I release the array, I do not get all of my memory back. The following example demonstrates my problem.

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:10];

    NSLog(@"The array has no elements!"); // Activity monitor says 1.5 megs
    [NSThread sleepForTimeInterval:10];

    NSUInteger i;
    for(i = 0;i < 1000000;i++)
    {
        NSString *str = [[NSString alloc] initWithFormat:@"Number=%d, again it is: %d, one more time for added length: %d", i, i, i];
        [array addObject:str];
        [str release];
    }

    NSLog(@"We have used lots of memory!"); // Activity Monitor says 108 megs
    [NSThread sleepForTimeInterval:5];

    [array release];
    NSLog(@"We have released the array!"); // Activity Monitor says 19 megs
    [NSThread sleepForTimeInterval:5];

    [pool drain];
    NSLog(@"We have drained the pool!"); // Activity Monitor still says 19 megs
    [NSThread sleepForTimeInterval:5];

    return 0;
}

I added calls to sleepForTimeInterval so I could see and note the memory usage listed by Activity Monitor. At each pause I have listed the amount of memory I am supposedly using. I am almost sure my problem stems from a misunderstanding in the retain/release conventions. Does anyone see where I am going wrong?

Upvotes: 1

Views: 390

Answers (3)

Darren
Darren

Reputation: 25619

Your code is correct.

I suggest using Instruments to inspect your object allocations. You should see that everything has been deallocated when you release your array.

The numbers you're seeing in Activity Monitor may be the result of some NSString memory caching performed by the Foundation, or it may simply be a function of the OS memory manager is handling your application.

Upvotes: 4

Dave Martorana
Dave Martorana

Reputation: 1331

Memory is cleaned up between run-loops.

[NSThread sleepForTimeInterval:n] 

blocks the thread, and no run-loop processing occurs.

http://developer.apple.com/mac/library/documentation/cocoa/reference/Foundation/Classes/NSThread_Class/Reference/Reference.html#jumpTo_12

You're not specifically deallocating memory, you're simply decrementing the retain count to 0, which will allow the runtime to clean up the memory at the next iteration of the run-loop.

"Objects that have been autoreleased during that time will be destroyed at the end of the run loop cycle..."

http://parmanoir.com/When_does_autorelease_release_%3F

Upvotes: -1

Matt Greer
Matt Greer

Reputation: 62057

Dang it, I just wrote a whole answer missing your [str release] call :)

Anyway, you aren't actually using the autorelease pool, as you are manually allocing everything yourself. If you instead use [NSString stringWithFormat...] and then don't release the strings, then you will be using the autorelease pool.

Upvotes: 1

Related Questions