[NSCalendar currentCalendar] leak

  • When testing my app using the leaks tool, I have an awful lot of
    leaked NSCalendar instances.  However, in my code, I only ever call
    [NSCalendar currentCalendar] which presumably should autorelease the
    instance.

    Does anyone know if I am missing something obvious here?

    I guess if this really is a bug, I'll just have to use the standard
    [[NSCalendar alloc] init] sequence.

    Mie.
  • On Tue, 31 Oct 2006 23:03:51 +0000, Mike Abdullah <mike.abdullah...>
    said:
    > When testing my app using the leaks tool, I have an awful lot of
    > leaked NSCalendar instances.  However, in my code, I only ever call
    > [NSCalendar currentCalendar] which presumably should autorelease the
    > instance.
    >
    > Does anyone know if I am missing something obvious here?

    Yes, it is obvious to do a search on currentCalendar to see whether this is
    known:

    <http://www.cocoabuilder.com/archive/message/cocoa/2006/7/16/167714>

    and it is obvious to add your voice to the list and help the community by
    reporting this as a bug:

    <https://bugreport.apple.com>

    m.
    --
    matt neuburg, phd = <matt...>, <http://www.tidbits.com/matt/>
    A fool + a tool + an autorelease pool = cool!
    AppleScript: the Definitive Guide - Second Edition!
    <http://www.amazon.com/gp/product/0596102119>
  • Thanks Matt, I'll report it.  Worries me slightly this bug though,
    especially since I know from experience that NSDateComponents doesn't
    conform to NSCoding.

    Mike.

    On 1 Nov 2006, at 00:01, Matt Neuburg wrote:

    > On Tue, 31 Oct 2006 23:03:51 +0000, Mike Abdullah
    > <mike.abdullah...>
    > said:
    >> When testing my app using the leaks tool, I have an awful lot of
    >> leaked NSCalendar instances.  However, in my code, I only ever call
    >> [NSCalendar currentCalendar] which presumably should autorelease the
    >> instance.
    >>
    >> Does anyone know if I am missing something obvious here?
    >
    > Yes, it is obvious to do a search on currentCalendar to see whether
    > this is
    > known:
    >
    > <http://www.cocoabuilder.com/archive/message/cocoa/2006/7/16/167714>
    >
    > and it is obvious to add your voice to the list and help the
    > community by
    > reporting this as a bug:
    >
    > <https://bugreport.apple.com>
    >
    > m.
    > --
    > matt neuburg, phd = <matt...>, <http://www.tidbits.com/matt/>
    > A fool + a tool + an autorelease pool = cool!
    > AppleScript: the Definitive Guide - Second Edition!
    > <http://www.amazon.com/gp/product/0596102119>
    >
    >
    >
  • Just for the archives, I implemented this category to fix the problem:

    @implementation NSCalendar (RealCurrentCalendar)

    // We are overriding the default implementation of currentCalendar
    since it leaks like a sieve.
    + (id)currentCalendar
    {
    NSString *localeIdentifier = [[NSLocale currentLocale] objectForKey:
    NSLocaleCalendar];

    NSCalendar *currentCalendar =
      [[[NSCalendar alloc] initWithCalendarIdentifier: localeIdentifier]
    autorelease];

    return currentCalendar;
    }

    @end

    On 1 Nov 2006, at 21:01, Mike Abdullah wrote:

    > Thanks Matt, I'll report it.  Worries me slightly this bug though,
    > especially since I know from experience that NSDateComponents
    > doesn't conform to NSCoding.
    >
    > Mike.
    >
    > On 1 Nov 2006, at 00:01, Matt Neuburg wrote:
    >
    >> On Tue, 31 Oct 2006 23:03:51 +0000, Mike Abdullah
    >> <mike.abdullah...>
    >> said:
    >>> When testing my app using the leaks tool, I have an awful lot of
    >>> leaked NSCalendar instances.  However, in my code, I only ever call
    >>> [NSCalendar currentCalendar] which presumably should autorelease the
    >>> instance.
    >>>
    >>> Does anyone know if I am missing something obvious here?
    >>
    >> Yes, it is obvious to do a search on currentCalendar to see
    >> whether this is
    >> known:
    >>
    >> <http://www.cocoabuilder.com/archive/message/cocoa/2006/7/16/167714>
    >>
    >> and it is obvious to add your voice to the list and help the
    >> community by
    >> reporting this as a bug:
    >>
    >> <https://bugreport.apple.com>
    >>
    >> m.
    >> --
    >> matt neuburg, phd = <matt...>, <http://www.tidbits.com/matt/>
    >> A fool + a tool + an autorelease pool = cool!
    >> AppleScript: the Definitive Guide - Second Edition!
    >> <http://www.amazon.com/gp/product/0596102119>
    >>
    >>
    >>
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/mike.abdullah%
    > 40gmail.com
    >
    > This email sent to <mike.abdullah...>
  • On Fri, 3 Nov 2006 19:11:13 +0000, Mike Abdullah <mike.abdullah...>
    said:
    > Just for the archives, I implemented this category to fix the problem:
    >
    > @implementation NSCalendar (RealCurrentCalendar)
    >
    > // We are overriding the default implementation of currentCalendar
    > since it leaks like a sieve.
    > + (id)currentCalendar
    > {
    > NSString *localeIdentifier = [[NSLocale currentLocale] objectForKey:
    > NSLocaleCalendar];
    >
    > NSCalendar *currentCalendar =
    > [[[NSCalendar alloc] initWithCalendarIdentifier: localeIdentifier]
    > autorelease];
    >
    > return currentCalendar;
    > }
    >
    > @end

    That sort of trick works if you know for an absolute fact what the framework
    is doing "wrong" and that it does it with perfect consistency, but here are
    two warnings: (1) You don't know this (how, for example, do you know for a
    fact that there might not be some cases where the framework does NOT
    over-retain the calendar?), and (2) behaviour might change in the future
    (since this over-retaining is obviously a bug). Thus you are risking a
    mysterious crash. I find it better practice not to try to second-guess
    leak-causing behavior by the framework. In reality, I would conjecture, you
    are probably not generating enough calendars for the leak to matter to your
    users; you yourself know about it only because you've been spending too much
    time hunched over ObjectAlloc. :)

    I say all this because that is how I "fixed" the leak I've just discovered
    in my AppleScript Studio hybrid Obj-C / AppleScript application. This is the
    framework's bug: two extra retains are added to a non-bridged object when
    "call method" receives it as it's result. I thought about and tried various
    ways of defeating the leak, but then I did some real-world measurements and
    decided that, in practice, no one would notice the leak unless they had
    fifty monkeys hammering away at the app for a month on end. So my "fix" was
    to walk away and stop worrying. m.

    --
    matt neuburg, phd = <matt...>, <http://www.tidbits.com/matt/>
    A fool + a tool + an autorelease pool = cool!
    AppleScript: the Definitive Guide - Second Edition!
    <http://www.amazon.com/gp/product/0596102119>
  • On 4 Nov 2006, at 15:16, Matt Neuburg wrote:

    > On Fri, 3 Nov 2006 19:11:13 +0000, Mike Abdullah
    > <mike.abdullah...>
    > said:
    >> Just for the archives, I implemented this category to fix the
    >> problem:
    >>
    >> @implementation NSCalendar (RealCurrentCalendar)
    >>
    >> // We are overriding the default implementation of currentCalendar
    >> since it leaks like a sieve.
    >> + (id)currentCalendar
    >> {
    >> NSString *localeIdentifier = [[NSLocale currentLocale] objectForKey:
    >> NSLocaleCalendar];
    >>
    >> NSCalendar *currentCalendar =
    >> [[[NSCalendar alloc] initWithCalendarIdentifier: localeIdentifier]
    >> autorelease];
    >>
    >> return currentCalendar;
    >> }
    >>
    >> @end
    >
    > That sort of trick works if you know for an absolute fact what the
    > framework
    > is doing "wrong" and that it does it with perfect consistency, but
    > here are
    > two warnings: (1) You don't know this (how, for example, do you
    > know for a
    > fact that there might not be some cases where the framework does NOT
    > over-retain the calendar?)

    But that's not an issue here since I'm completely overriding the -
    currentCalendar method.  The framework no longer gets a chance to
    over-retain anything.

    > , and (2) behaviour might change in the future
    > (since this over-retaining is obviously a bug). Thus you are risking a
    > mysterious crash.

    Again, not a problem.  If the framework changes, my implementation
    will still be used.

    > I find it better practice not to try to second-guess
    > leak-causing behavior by the framework. In reality, I would
    > conjecture, you
    > are probably not generating enough calendars for the leak to matter
    > to your
    > users; you yourself know about it only because you've been spending
    > too much
    > time hunched over ObjectAlloc. :)

    In my app I call and use -currentCalendar rather a lot!  My app
    performs a lot of conversion between NSDate and NSDateComponents and
    the leak was pretty obvious using the leaks command line tool.

    In fact, not only does an instance of NSCalendar get leaked, but so
    does an NSLocale and other object (can't remember what off the top of
    my head!).  So, whilst it doesn't have a huge impact on memory, it
    does make future use of the leaks tool rather awkward since the list
    is cluttered up with many instances like this.
    >
    > I say all this because that is how I "fixed" the leak I've just
    > discovered
    > in my AppleScript Studio hybrid Obj-C / AppleScript application.
    > This is the
    > framework's bug: two extra retains are added to a non-bridged
    > object when
    > "call method" receives it as it's result. I thought about and tried
    > various
    > ways of defeating the leak, but then I did some real-world
    > measurements and
    > decided that, in practice, no one would notice the leak unless they
    > had
    > fifty monkeys hammering away at the app for a month on end. So my
    > "fix" was
    > to walk away and stop worrying. m.
    >
    > --
    > matt neuburg, phd = <matt...>, <http://www.tidbits.com/matt/>
    > A fool + a tool + an autorelease pool = cool!
    > AppleScript: the Definitive Guide - Second Edition!
    > <http://www.amazon.com/gp/product/0596102119>
    >
    >
    >
  • On Nov 5, 2006, at 8:50 AM, Mike Abdullah wrote:
    > Again, not a problem.  If the framework changes, my implementation
    > will still be used.

    Which begs the question, what use is it for you to override
    "currentCalendar" at all? This technique of using a category to
    "override" seems very fragile to me. I can't imagine there is a
    guarantee that yours will override the original, except that by luck
    it happens to be loaded dynamically later than the original.

    If I was in your position I would take the much less fragile approach
    of simply defining your own uniquely named method
    "currentCalendarWithoutLeaking," and use that throughout your code.

    What matt was getting at, I think, is it's dangerous to make
    assumptions about what the opaque framework is normally doing behind
    your back. He's right. You might think it's obvious that replacing a
    method like this outright is a safe thing to do, and it probably is,
    but you could definitely be wrong.

    At the very least we might at least examine what's going on in the
    method, to reassure ourselves.

    bl      0x92adb880 <dyld_stub_CFCalendarCopyCurrent>
    bl      0x92ad49a0 <dyld_stub_CFMakeCollectable>
    lwz    r0,88(r1)
    addis  r4,r31,4076
    addi    r1,r1,80
    lwz    r4,-15100(r4)
    mtlr    r0
    lmw    r30,-8(r1)
    ba      0xfffeff00 <objc_msgSend_rtp>

    By looking at what "currentCalendar" actually does, we not only get a
    great idea of how we can best imitate it, we also see exactly what's
    causing the bug. Oops! Apple is using garbage collection to manage
    the memory for this object. Apparently somebody didn't get the memo
    that this wasn't going in for 10.4.

    Since CFCalendar is toll-free bridged to NSCalendar, my non-leaking
    version, if I was using this method, would look something like this:

    - (NSCalendar*) currentCalendarWithoutLeaking
    {
        // NSCalendar and CFCalendar are toll-free bridged
        NSCalendar* currentCalendar = (NSCalendar*) CFCalendarCopyCurrent
    ();
        return [currentCalendar autorelease];
    }

    Now you've got a reliable method that doesn't get its hands dirty
    overriding existing methods, is known to have identical conceptual
    behavior to the existing implementation, and guaranteed to have long-
    lived conceptual correctness in its own right.

    Daniel
  • On Nov 5, 2006, at 8:01 AM, Daniel Jalkut wrote:
    > By looking at what "currentCalendar" actually does, we not only get
    > a great idea of how we can best imitate it, we also see exactly
    > what's causing the bug. Oops! Apple is using garbage collection to
    > manage the memory for this object. Apparently somebody didn't get
    > the memo that this wasn't going in for 10.4.

    Or CFMakeCollectable() does nothing in a non-GC'd runtime, thus
    enabling a binary to be shared between GC'd and non-GC'd applications...

    b.bum
  • On Nov 5, 2006, at 08:01, Daniel Jalkut wrote:

    > On Nov 5, 2006, at 8:50 AM, Mike Abdullah wrote:
    >> Again, not a problem.  If the framework changes, my implementation
    >> will still be used.
    >
    > Which begs the question, what use is it for you to override
    > "currentCalendar" at all?

    It would keep underlying code in the frameworks that uses
    +currentCalendar from leaking (not to speak for Mike...that would be
    my reason for it).

    > This technique of using a category to "override" seems very fragile
    > to me. I can't imagine there is a guarantee that yours will
    > override the original, except that by luck it happens to be loaded
    > dynamically later than the original.

    I believe the category is loaded after the class, so this will work
    unless Apple puts +currentCalendar in a category; in that case, it's
    undefined which one will win out.  It's likely that this won't happen
    on 10.4, at least, but using something like Omni's OBReplaceMethod...
    functions may be more reliable, and you can decide at runtime whether
    to replace the method or not.

    [...]

    > At the very least we might at least examine what's going on in the
    > method, to reassure ourselves.
    >
    > bl      0x92adb880 <dyld_stub_CFCalendarCopyCurrent>
    > bl      0x92ad49a0 <dyld_stub_CFMakeCollectable>
    > lwz    r0,88(r1)
    > addis  r4,r31,4076
    > addi    r1,r1,80
    > lwz    r4,-15100(r4)
    > mtlr    r0
    > lmw    r30,-8(r1)
    > ba      0xfffeff00 <objc_msgSend_rtp>
    >
    > By looking at what "currentCalendar" actually does, we not only get
    > a great idea of how we can best imitate it, we also see exactly
    > what's causing the bug. Oops! Apple is using garbage collection to
    > manage the memory for this object. Apparently somebody didn't get
    > the memo that this wasn't going in for 10.4.

    I've seen various garbage collection calls in my code when running
    under Shark, and it doesn't leak.  My guess was that this is
    available to CF, but I could be wrong on that.

    Adam
  • On Nov 5, 2006, at 2:04 PM, Bill Bumgarner wrote:

    > On Nov 5, 2006, at 8:01 AM, Daniel Jalkut wrote:
    >> By looking at what "currentCalendar" actually does, we not only
    >> get a great idea of how we can best imitate it, we also see
    >> exactly what's causing the bug. Oops! Apple is using garbage
    >> collection to manage the memory for this object. Apparently
    >> somebody didn't get the memo that this wasn't going in for 10.4.
    >
    > Or CFMakeCollectable() does nothing in a non-GC'd runtime, thus
    > enabling a binary to be shared between GC'd and non-GC'd
    > applications...

    Good point - my speculation was unnecessarily negative.

    Daniel
  • Thanks very much for the feedback guys.  I think Daniel's probably
    right and that I should really be using CFCalendarCopyCurrent() in my
    implementation.

    Additionally, I think he's correct and that I should avoid using a
    category to override this method.  Instead, I shall just create a
    different method -nonLeakyCurrentCalendar and call that in my code.

    I shall also look into OBReplaceMethod, I hadn't previously
    considered swizzling.

    Mike.

    On 5 Nov 2006, at 19:17, Adam R. Maxwell wrote:

    >
    > On Nov 5, 2006, at 08:01, Daniel Jalkut wrote:
    >
    >> On Nov 5, 2006, at 8:50 AM, Mike Abdullah wrote:
    >>> Again, not a problem.  If the framework changes, my
    >>> implementation will still be used.
    >>
    >> Which begs the question, what use is it for you to override
    >> "currentCalendar" at all?
    >
    > It would keep underlying code in the frameworks that uses
    > +currentCalendar from leaking (not to speak for Mike...that would
    > be my reason for it).
    >
    >> This technique of using a category to "override" seems very
    >> fragile to me. I can't imagine there is a guarantee that yours
    >> will override the original, except that by luck it happens to be
    >> loaded dynamically later than the original.
    >
    > I believe the category is loaded after the class, so this will work
    > unless Apple puts +currentCalendar in a category; in that case,
    > it's undefined which one will win out.  It's likely that this won't
    > happen on 10.4, at least, but using something like Omni's
    > OBReplaceMethod... functions may be more reliable, and you can
    > decide at runtime whether to replace the method or not.
    >
    > [...]
    >
    >> At the very least we might at least examine what's going on in the
    >> method, to reassure ourselves.
    >>
    >> bl      0x92adb880 <dyld_stub_CFCalendarCopyCurrent>
    >> bl      0x92ad49a0 <dyld_stub_CFMakeCollectable>
    >> lwz    r0,88(r1)
    >> addis  r4,r31,4076
    >> addi    r1,r1,80
    >> lwz    r4,-15100(r4)
    >> mtlr    r0
    >> lmw    r30,-8(r1)
    >> ba      0xfffeff00 <objc_msgSend_rtp>
    >>
    >> By looking at what "currentCalendar" actually does, we not only
    >> get a great idea of how we can best imitate it, we also see
    >> exactly what's causing the bug. Oops! Apple is using garbage
    >> collection to manage the memory for this object. Apparently
    >> somebody didn't get the memo that this wasn't going in for 10.4.
    >
    > I've seen various garbage collection calls in my code when running
    > under Shark, and it doesn't leak.  My guess was that this is
    > available to CF, but I could be wrong on that.
    >
    > Adam
    >
previous month november 2006 next month
MTWTFSS
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30      
Go to today