MailCore / mailcore2

MailCore 2 provide a simple and asynchronous API to work with e-mail protocols IMAP, POP and SMTP. The API has been redesigned from ground up.
Other
2.59k stars 623 forks source link

Fix NSCoding memory leak #1918

Closed KaiOelfke closed 2 years ago

KaiOelfke commented 3 years ago

I use MailCore in an iOS app. My app uses NSCoding to cache messages on disk. But I noticed a memory leak via the debugging tools. Each decoded instance leaks.

This can be reproduced with a sample project containing code like:

-(void)testCoding {
    MCOIMAPMessage *message = [[MCOIMAPMessage alloc] init];

    NSError *error;
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:message requiringSecureCoding:NO error:&error];

    for (int i = 0; i<5; i++) {
        MCOIMAPMessage *msg = [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:data error:&error];
        NSLog(@"%@", msg);
    }
}

Note: The test code uses automatic reference counting.

leak

The MCO_SYNTHESIZE_NSCODING macro implements NSCoding.

The initWithCoder initializer always replaces the originally allocated instance of self with the return value of [NSObject mco_objectWithMCObject:] (see the MCO_TO_OBJC macro). In such cases the originally allocated instance should be released. This is explained in detail here:

Apple documentation

"After setting instance variables to valid initial values, return self unless:

  • It was necessary to return a substituted object, in which case release the freshly allocated object first (in memory-managed code)."

I successfully tested the change in my app and my sample, but nothing else. I also didn't write any manual reference count code since 10 years so please review, if this fix makes sense.

dinhvh commented 2 years ago

Thank you!