bookmarkDataWith is taking a leak on me

Discussion in 'Mac Programming' started by zeppenwolf, Jan 7, 2015.

  1. zeppenwolf macrumors regular

    zeppenwolf

    Joined:
    Nov 17, 2009
    #1
    The Leaks Instrument identifies a call to bookmarkDataWithContentsOfURL: as a leak. The code is next, although I don't think there's much to see:

    Code:
    NSURL* applFromAlias( NSURL* aliasURL ) {
    
        NSData*     bookmark    = [NSURL bookmarkDataWithContentsOfURL:aliasURL error:0]; // LEAK
        if ( ! bookmark )
            return 0;
    
        NSError*    error       = 0;
        NSURL*      original    = [NSURL
            URLByResolvingBookmarkData:bookmark
                               options:NSURLBookmarkResolutionWithoutUI
                         relativeToURL:0
                   bookmarkDataIsStale:0
                                 error:&error];
    
    //  [bookmark autorelease]; // BURN
    
        if ( error )
            return 0;
    
        return original;
    }
    The History pane of the Leaks instrument shows a single malloc() of type CFData, size 48, at the line marked LEAK above... Well, ok. By the naming of bookmarkDataWithContentsOfURL: I really really thought that it should be an autoreleased object returned...

    But if I suppose for a moment that I'm wrong, or even that Apple might have made a silly mistake, I think to myself, "ok, so it's not autoreleased-- I'll add that line myself". If I do that, ( uncomment the line marked BURN ), then instead of the fixing the problem, the app bursts into flames in a short while. Profiling Zombies in that case, I get the following, quite different history for the returned object, ( I abbrev'ed autorelease for the sake of forum posting ) :

    Code:
    0   0x1006f8fb0 CFData  Malloc      1   00:37.454.427   512 DockMotor   applFromAlias
    1   0x1006f8fb0 CFData  A'lease     -   00:37.454.470   0   DockMotor   applFromAlias
    2   0x1006f8fb0 CFData  CFRetain    2   00:37.454.531   0   DockMotor   applFromAlias
    3   0x1006f8fb0 CFData  CFRelease   1   00:37.454.660   0   DockMotor   applFromAlias
    4   0x1006f8fb0 CFData  A'lease     -   00:37.454.662   0   DockMotor   applFromAlias
    5   0x1006f8fb0 CFData  CFRelease   0   00:37.454.887   0   AppKit  NSCoreDragTrackingProc
    6   0x1006f8fb0 CFData  Zombie      -1  00:37.454.910   0   AppKit  NSCoreDragTrackingProc
    
    So, in short: if I don't add an autorelease, then I get a leak. If I do add an autorelease, then I get a zombie.

    I find that just a wee bit aggravating. Am I missing something? What's going on here??
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    I would try comparing the results of the class method with the results from the NSURL instance method bookmarkDataWithOptions:... even if it means using no options, no keys, no relative URL, etc.

    I'd also play around with different options and see if anything interesting falls out of the tree.

    To me, it seems likely the class method just calls the instance method while doing some other unknown stuff internally. It seems unlikely the instance method would call the class method, since the latter has fewer args.


    Which OS version is this on?

    I also assume you're using retain/release and not ARC, otherwise this would be unnecessary.
     
  3. zeppenwolf thread starter macrumors regular

    zeppenwolf

    Joined:
    Nov 17, 2009
    #3
    I see what you were thinking, and it was a clever idea, thanks for that.

    But you missed a nuance in all these function names...

    "bookmarkDataWithContentsOfURL:" takes the URL of an "alias" file in the Finder and resolves it to the original, which is what I need in this case.

    "bookmarkDataWithOptions" just creates an "aliasRecord", if you will, from the URL passed to it, which serves no purpose here.

    I took your idea and looked through the header, but sadly there is no suitable member function like "bookmarkDataWithContentsOfMe" there.

    Yes, I should have mentioned, I'm using XCode 420 on X.6 Snow... I'm still vaguely hoping to release my app with back-compatibilty to X.6, tho as times goes on it seems more and more likely that I'll give that up and just go back to X.7

    Yes, release/retain. It was good enough for my grandfather, dang it, and...
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    Look at CFURL. It's toll-free bridged with NSURL, so see if it says something in its docs that clarifies NSURL's handling of bookmark data.

    The only other solution I can think of is to use the traditional Alias Manager as the fallback, and choose it when the OS version is 10.6. If the problem is specific to an OS version, then falling back to Alias Manager might avoid it. If the problem is pervasive in every OS version's NSURL bookmark handling, then it won't.

    Finally, maybe the Leaks tool is wrong, and autoreleasing is "solving" a problem that doesn't actually exist.
     
  5. zeppenwolf thread starter macrumors regular

    zeppenwolf

    Joined:
    Nov 17, 2009
    #5
    Your suspicion that it might be only a X.6 problem appears to be correct. To be accurate, I jumped onto X.7 and changed the BaseSDK to 7, and voila! It's gone, even though I left Deployment Target at X.6, in fact.

    As always, chown33, thanks for the thinks !
     

Share This Page