How can I free this NSXMLParser without crashing my application?

Below is @interface for MREntitiesConverter object which I am using to strip all html tags from string using NSXMLParser.

@interface MREntitiesConverter : NSObject {
    NSMutableString* resultString;
    NSString* xmlStr;
    NSData *data;
    NSXMLParser* xmlParser;
}
@property (nonatomic, retain) NSMutableString* resultString;
- (NSString*)convertEntitiesInString:(NSString*)s;
@end

      

And this is the implementation:

@implementation MREntitiesConverter
@synthesize resultString;
- (id)init
{
    if([super init]) {
        self.resultString = [NSMutableString string];
    }
    return self;
}

- (NSString*)convertEntitiesInString:(NSString*)s {
    xmlStr = [NSString stringWithFormat:@"<data>%@</data>", s];
    data = [xmlStr dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
    xmlParser = [[NSXMLParser alloc] initWithData:data];

    [xmlParser setDelegate:self];
    [xmlParser parse];

    return [resultString autorelease];
}

- (void)dealloc {
    [data release];
    //I want to release xmlParser here but it crashes the app
    [super dealloc];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)s {
    [self.resultString appendString:s];
}
@end

      

If I free xmlParser

in the dealloc method, I crash my application, but without freeing, I am clearly losing memory.

I am new to Tools and am trying to optimize this application. Any help you can offer on this specific issue will probably help me solve other memory issues in my application.

Your disappointment :) Oisin

+2


a source to share


6 answers


Both classes and NSXMLParser free the data, causing your current crash. The only member must be resultString. You must initialize the resultString to convertEntitiesInString: not init, so the same instance can be used multiple times. You should return either self.resultString or [[save resultString] autorelease] from convert because what you are doing now will result in a double release later if you free the resultString in dealloc as you would expect. You should use resultString directly in parser: foundCharacters: instead of self.resultString which is a method call.



+3


a source


I do not see to xmlParser

be used outside convertEntitiesInString:

. You can make it xmlParser

local to this method (not an instance variable) and drop it when you're done with it in that method, before the line return [resultString autorelease]

.



+2


a source


Are you sure the [xmlParser release] application crashes in dealloc? I see that you have a [data release] in your dealloc and I cannot see an instruction where you used alloc to allocate memory to it.

+2


a source


While the other two comments are correct (you forget the release

parser in the method you are alloc

, it is a memory leak), I am pretty sure this is a glitch because you set your class to be MREntitiesConverter

like a delegate

parser.

0


a source


I believe it is the result ofString that is causing the crash. It's an NSMutableString and you haven't allocated any memory for it. Also free the xmlParser in convertEntitiesInString before returning [resultString autorelease];

0


a source


Based on some really helpful suggestions, this is the latest version of my code that doesn't seem to waste memory:

@interface MREntitiesConverter : NSObject {
    NSMutableString* resultString;
}
@property (nonatomic, retain) NSMutableString* resultString;
- (NSString*)convertEntitiesInString:(NSString*)s;
@end


@implementation MREntitiesConverter
@synthesize resultString;

- (NSString*)convertEntitiesInString:(NSString*)s {
    self.resultString = [NSMutableString string];

    NSString* xmlStr = [NSString stringWithFormat:@"<d>%@</d>", s];
    NSData *data = [xmlStr dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
    NSXMLParser* xmlParse = [[NSXMLParser alloc] initWithData:data];

    [xmlParse setDelegate:self];
    [xmlParse parse];
    [xmlParse release];

    return [self.resultString autorelease];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)s {
    [resultString appendString:s];
}
@end

      

The only oddity is that if I trace retainCount

from resultString

just before returning, I get the counter 2

where I expected it to be 1

. Any idea why?

0


a source







All Articles