質問

In an iOS app, I'm kicking off several background threads to process some XML that comes back from a REST service.

I have a few users who are experiencing intermittent crashing at the [self.names addObject: name] line of code in PeopleParser.m. The crash logs don't indicate the reason, only the line of code where it crashed. I'm unable to reproduce the crash so I'm assuming it's memory related. Is it possible that my *xml object is being released, possibly by the main thread pool, before my for-loop is finished with it? Notice I'm not declaring an autorelease pool in my background thread.

Fetcher.m

-(void) peopleFetchComplete:(ASIHTTPRequest *)theRequest {

    dispatch_async( backgroundQueue, ^{
       PeopleParser *xmlParse = [[PeopleParser alloc] initWithContext:[self managedObjectContext]];
       [xmlParse parseXMLData:[theRequest responseData] parseError:&parseError];
       [xmlParse release];
    });
}

PeopleParser.h

@interface PeopleParser : NSObject {
    NSMutableArray *names;
    ...
}

-(void)parseXMLData:(NSData *)data parseError:(NSError **)error;

@property (retain, nonatomic) NSMutableArray *names;

PeopleParser.m

-(id)initWithContext:(NSManagedObjectContext *)managedObjContext{
    self = [super init];
    self.managedObjectContext = managedObjContext;
    names = [[NSMutableArray alloc] init];
    return self;
}

-(void)dealloc{
    [names release];
    [managedObjectContext release];
}

@synthesize names;

-(void)parseXMLData {

    //documentWithData returns an autorelease object
    SMXMLDocument *xml = [SMXMLDocument documentWithData:someNSData error:nil];
    NSArray *people = [[document root] children];

    for (SMXMLElement *element in people) {
        NSString *name = [element attributeNamed:@"personName"];
        [self.names addObject: name];  //CRASHES HERE occasionally 
    }

    //do additional stuff with the data
    ...
}

Crash Log

Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Crashed Thread: 7

Last Exception Backtrace:

0 CoreFoundation 0x3465229e __exceptionPreprocess + 158

1 libobjc.A.dylib 0x3c37a97a objc_exception_throw + 26

2 CoreFoundation 0x3459c8d4 -[__NSArrayM insertObject:atIndex:] + 764

3 MyApp 0x000fee36 -[PeopleParser parseXMLData:parseError:] (PeopleParser.m:62)

4 MyApp 0x000e9b4c __50-[Fetcher peopleFetchComplete:]_block_invoke (Fetcher.m:818)

役に立ちましたか?

解決

It is possible that "self.names" gets deallocated before the block is executed. Make sure to cancel block operation or protect this class from being deallocated (by blocking a screen with loading screen) so users cannot go back.

It can happen for example on unloadView or places like that (if you paste more code it will be maybe more accurate).

Based on that I think exception is called from insertObject method - which means you are trying to insert a "nil" object most likely. Try adding if(name) { } before adding it to array - maybe there is something wrong with XML file in that case.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top