0

in a project using garbage collection: Clang alerts 'Potential null dereference....' on line assigning *anError.

But this look right to me according to: Why does NSError need double indirection? (pointer to a pointer)

Can anyone see what i'm not seeing ?

- (NSData *)bookmarkDataForCurrentURL:(NSURL *)theURL error:(NSError **)anError
{
    NSArray *bkKeys = [CBPrepCommon bookmarkPropertyKeys];
    NSError *errorA = nil;
    NSData *bkmark = [theURL bookmarkDataWithOptions:NSURLBookmarkCreationPreferFileIDResolution includingResourceValuesForKeys:bkKeys relativeToURL:nil error:&errorA];

    if (![bkmark length] > 0) {
    if (errorA) {
        // error here
        *anError = [NSError errorWithDomain:[errorA domain] code:[errorA code] userInfo:[errorA userInfo]];
    }
    return nil;
}
return bkmark;

}

Community
  • 1
  • 1
lulu
  • 669
  • 10
  • 26
  • It looks OK to me too, assuming that your incoming parameters are good. Does the message go away if you put `if (anError) {...}` around your assignment to `*anError`? – Phillip Mills Jun 07 '12 at 15:50
  • yes, but i don't understand why or how if (anError) { *anError = [NSError errorWithDomain:[errorA domain] code:[errorA code] userInfo:[errorA userInfo]]; } would be called ? – lulu Jun 07 '12 at 15:55
  • It's telling you that you're not protected from the case of something calling `NSData *data = [anObject bookmarkDataForCurrentURL:theURL error:nil];`, which is true but not something a compiler has typically concerned itself with. – Phillip Mills Jun 07 '12 at 15:59
  • do i check at the top to see if anError isn't referenced -- not sure how to write that...if &anError == nil { return; }, because the caller is declaring NSError *errorX = nil, then plugging that into the method call as &errorX. – lulu Jun 07 '12 at 16:08
  • 1
    You could try `if (!anError) {return;}`. I don't know if that will make the compiler happy or not...or you could leave the test as you have it in the above comment. – Phillip Mills Jun 07 '12 at 16:13
  • thanks phillip, for helping me think this through. i can't mark you comments as an answer, so no way to add to your rep except upvote your comment. – lulu Jun 07 '12 at 16:16
  • Something similar happened to me, but on iOS (no GC, no ARC). I had forgotten to initialize the NSError variable to nil before passing the reference. But your code seems to have that one covered... – Nicolas Miari Jun 15 '12 at 21:07

1 Answers1

0
if (errorA && anError) {
    // error here
    *anError = [NSError errorWithDomain:[errorA domain] code:[errorA code] userInfo:[errorA userInfo]];
}

EDIT: Even cleaner:

- (NSData *)bookmarkDataForCurrentURL:(NSURL *)theURL error:(NSError **)anError
{
    NSArray *bkKeys = [CBPrepCommon bookmarkPropertyKeys];
    NSData *bkmark = [theURL bookmarkDataWithOptions:NSURLBookmarkCreationPreferFileIDResolution includingResourceValuesForKeys:bkKeys relativeToURL:nil error:anError];

    if ([bkmark length] == 0) {
        return nil;
    }

    return bkmark;
}
Anonymous
  • 1,750
  • 3
  • 16
  • 21
  • Also, what are you using theURL for? You're passing nil to bookmarkDataWithOptions:includingResourceValuesForKeys:relativeToURL:error. – Anonymous Jun 12 '12 at 19:02
  • i'm passing it in as a property of a NSManagedObject, during the managedObject's creation, so its okay for it to be nil, i think, so i can fail the NSManagedObject's creation in the caller's method, and examine the error. your second idea produces a warning for me 'incompatible pointer types sending NSError***] to 'NSError **' – lulu Jun 14 '12 at 21:04
  • Typo. Changed &anError to just anError, that should fix the warning. – Anonymous Jun 15 '12 at 20:14