tags:

views:

45

answers:

2

Sometimes I wonder where I would be able to get great information other than from the stack overflow community. I suppose the Objective-C memory management handbook wouldn't be bad, but I feel like you guys can tell me why as opposed to just what to do.

I have the following code:

NSString* rawTickerData = [[NSString alloc] initWithData: op.requestData encoding:NSUTF8StringEncoding];
NSArray* lines   = [rawTickerData componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

for(NSString* line in lines)
{
    NSArray* fields = [line componentsSeparatedByString:@","];

    if([fields count] > 1)
    {
        [self.tickerData addObject:fields];
    }
}
    [rawTickerData release]

Instruments tells me that fields is leaking, but trying to release it after the if statement or doing an autorelease gives an EXC_BAD_ACCESS.

The same thing happens for lines. Releasing it anywhere or trying to do autorelease gives EXC_BAD_ACCESS or "trying to double free" (for autorelease).

Yet, instruments is still saying that these are leaking. Am I missing something?

+1  A: 

Unless I'm missing something, the code you've posted is correct. fields is an autoreleased object that gets retained when added to self.tickerData. lines is also autoreleased, so it isn't leaking (at least not in the code shown).

If you're leaking anywhere, it's because you're not properly cleaning up self.tickerData. If you comment out the [self.tickerData addObject:fields]; line, are you still getting leaks reported? If not, make sure you're calling [tickerData release] (or something similar, like self.tickerData = nil) somewhere, probably in your dealloc implementation.

Robot K
Robot K, I marked you as correct, because you were right that the tickerData wasn't being released. You also set me on the right path by saying fields and lines are autoreleased.
Jud Stephenson
A: 

In these cases the best practice is to release your object's at the end of each loop, if you retained them. In this case your fields variable gets an autorelease object, the best option is to use an NSAutoReleasePool to release your objects at the end of the loop.

NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];

NSString* rawTickerData = [[NSString alloc] initWithData: op.requestData encoding:NSUTF8StringEncoding];
NSArray* lines   = [rawTickerData componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

for(NSString* line in lines)
{
    NSArray* fields = [line componentsSeparatedByString:@","];

    if([fields count] > 1)
    {
        [self.tickerData addObject:fields];
    }
    [pool drain];
}
[rawTickerData release];

This will flushes all the autoreleased objects if they are don't needed. If you dont use autorelease pool, your objects are living until your method terminates. If this doesn't resolve your leak problem i suggest to initialize your array like this:

NSArray *lines = [[NSArray alloc]initWithArray:[line componentsSeparatedByString:@","]];
//and release at the end of the loop
[lines release];
dombesz