Over-released Paragraph Style - Driving Me NUTS!

  • PLEASE OH PLEEEEEEEEAAAAAAAAASSSSSSSEEEEEEEEEEE HELP ME!!!!!

    Hi,

    I have a paragraph style that's being over released somehow and for
    the life of me I can't figure it out. I appear to have narrowed it
    down to the code below, but it doesn't make any sense to me how this
    is causing a problem. The code below is tweaked to make it simpler
    for appearance and limiting class involvement, but it's functionally
    identical as the actual code.

    In a singleton class I have a paragraph style being created and set:

    - (void)setDefaultParagraph:(NSParagraphStyle *)paragraph
    {
        [paragraph retain];
        [defaultParagraph release];
        defaultParagraph = paragraph;
    }

    - (NSParagraphStyle *)defaultParagraph
    {
        return defaultParagraph;
    }

    - (NSParagraphStyle *)buildParagraphStyle:(NSFont *)font;
    {
        NSMutableParagraphStyle * ps = [[[NSMutableParagraphStyle alloc]
    init] autorelease];
        ...
        return ps;
    }

    - (id)init;
    {
        defaultParagraph = [[self buildParagraphStyle:font] retain];
    }

    Pretty straight forward and correct so far...

    This seems to be the part causing the problem. In a NSTextStorage
    subclass:

    - (NSDictionary *)attributesAtIndex:(unsigned)index effectiveRange:
    (NSRange *)r
    {
        .......

        NSMutableDictionary * d = [NSMutableDictionary
    dictionaryWithDictionary:[language dictionary]];
        //// If I simply change the above to d = [NSMutableDictionary
    dictionary] the over-release doesn't occur.

        [d removeObjectForKey:NSFontAttributeName];
        NSMutableDictionary * d2 = [NSMutableDictionary
    dictionaryWithDictionary:[store attributesAtIndex:index
    effectiveRange:r]];
        [d2 addEntriesFromDictionary:d];

        .......

        return d2;
    }

    The language class has:

    - (id)init;
    {
        NSParagraphStyle * pgs = [[Singleton defaultInstance]
    defaultParagraph];

        dictionary = [[NSMutableDictionary alloc] init];
        [dictionary setObject:pgs forKey:NSParagraphStyleAttributeName];
    }

    - (NSDictionary *)dictionary;
    {
        return dictionary;
    }

    The over-release is happening in the autorelease pool when a
    dictionary is being released. In other words, the stack trace is:

    #0    0x9297c008 in -[NSException raise]
    #1    0x9297be5c in +[NSException raise:format:]
    #2    0x907d32c0 in __CFDictionaryDeallocate
    #3    0x907bcf34 in _CFRelease
    #4    0x9293d968 in NSPopAutoreleasePool
    #5    0x93707d34 in -[NSApplication run]
    #6    0x937f887c in NSApplicationMain
    #7    0x00011240 in main at main.m:13

    *** Selector 'release' sent to dealloced instance 0x15138890 of class
    NSMutableParagraphStyle.

    The paragraph style is definitely without a doubt the one being
    created in the singleton, but what on earth is wrong about the code
    above? Am I THAT blind?

    --
    Seth Willits
  • > - (id)init;
    > {
    > NSParagraphStyle * pgs = [[Singleton defaultInstance]
    > defaultParagraph];
    >
    > dictionary = [[NSMutableDictionary alloc] init];
    > [dictionary setObject:pgs forKey:NSParagraphStyleAttributeName];
    > }

    Is your init method for the language class missing return self?

    - Chris
  • On Oct 19, 2006, at 6:17 PM, Chris Suter wrote:

    >> - (id)init;
    >> {
    >> NSParagraphStyle * pgs = [[Singleton defaultInstance]
    >> defaultParagraph];
    >>
    >> dictionary = [[NSMutableDictionary alloc] init];
    >> [dictionary setObject:pgs forKey:NSParagraphStyleAttributeName];
    >> }
    >
    > Is your init method for the language class missing return self?

    No. Like I said, the code was simplified to be applicable. It's all
    structurally correct.

    --
    Seth Willits
  • On 20 okt 2006, at 03.07, Seth Willits wrote:

    > The paragraph style is definitely without a doubt the one being
    > created in the singleton, but what on earth is wrong about the code
    > above? Am I THAT blind?

    You should be able to find your problem like this:

    Launch your app with ObjectAlloc. Tell ObjectAlloc to record all
    retain / release events, and backtraces. Run until you hit the
    problem. Locate the specific object that is causing the problem in
    ObjectAlloc, and then check the backtraces to all retain / release
    events.

    j o a r
  • On Oct 19, 2006, at 10:57 PM, j o a r wrote:

    >> The paragraph style is definitely without a doubt the one being
    >> created in the singleton, but what on earth is wrong about the
    >> code above? Am I THAT blind?
    >
    > You should be able to find your problem like this:
    >
    > Launch your app with ObjectAlloc. Tell ObjectAlloc to record all
    > retain / release events, and backtraces. Run until you hit the
    > problem. Locate the specific object that is causing the problem in
    > ObjectAlloc, and then check the backtraces to all retain / release
    > events.

    I've never used ObjectAlloc before, so it sounds neat. However, it's
    been running for the last half an hour and still hasn't gotten to the
    100% repeatable crash yet on a dual 2.3 G5. This is rather painful...

    --
    Seth Willits
  • On 20 okt 2006, at 20.34, Seth Willits wrote:

    > I've never used ObjectAlloc before, so it sounds neat. However,
    > it's been running for the last half an hour and still hasn't gotten
    > to the 100% repeatable crash yet on a dual 2.3 G5. This is rather
    > painful...

    ObjectAlloc is incredibly neat! It's an indispensable part of the
    Cocoa toolkit! There is also OmniObjectMeter from the good fellows at
    OmniGroup, I think it provides roughly the same functionality.

    Now, ObjectAlloc does require a lot of resources - especially in the
    configuration I advised you to use. It's particularly important to
    have lots of RAM. If you start swapping, you're basically toast.
    Check with Activity Monitor / top to see if you're OK on that front
    or not.

    It also helps if you can get to the problematic code as quickly as
    possible after launching your app. Perhaps you can tweak it a bit to
    avoid having it load / run other parts of your code while
    troubleshooting this issue? You might even want to try moving your
    problematic code to a small sample application.

    j o a r
  • On Oct 20, 2006, at 1:15 PM, j o a r wrote:

    >> I've never used ObjectAlloc before, so it sounds neat. However,
    >> it's been running for the last half an hour and still hasn't
    >> gotten to the 100% repeatable crash yet on a dual 2.3 G5. This is
    >> rather painful...
    >
    > ObjectAlloc is incredibly neat! It's an indispensable part of the
    > Cocoa toolkit! There is also OmniObjectMeter from the good fellows
    > at OmniGroup, I think it provides roughly the same functionality.
    >
    > Now, ObjectAlloc does require a lot of resources - especially in
    > the configuration I advised you to use. It's particularly important
    > to have lots of RAM. If you start swapping, you're basically toast.
    > Check with Activity Monitor / top to see if you're OK on that front
    > or not.
    >
    > It also helps if you can get to the problematic code as quickly as
    > possible after launching your app. Perhaps you can tweak it a bit
    > to avoid having it load / run other parts of your code while
    > troubleshooting this issue? You might even want to try moving your
    > problematic code to a small sample application.

    I got it working. I have two and a half gigs of RAM, so that's not an
    issue. I don't know why, but the app gets to a certain spot and just
    sits and does nothing after a certain point unless I attach the
    debugger to it after launching it with ObjectAlloc.

    The crash occurs while opening and initially displaying a text
    document, so what I did was launch it with ObjectAlloc, attach the
    debugger, pause and find the pointer value of the paragraph style
    that's getting clobbered, and then continued and opened the doucment.
    After a while later (and figuring out I had to call continue in gdb
    because of some weirdness) it finally hit the exception and I was
    able to find the pointer in ObjectAlloc.

    The only thing is that it didn't help me at all. There are three
    events for the object, the alloc, the autorelease, and the free. The
    alloc is from the buildParagraphStyle method, the autorelease is from
    the same, and the release is from the autorelease pool. Despite
    checking the box to manage retain and release calls, they were not,
    so I have no more information than when I started. Am I missing
    something?

    --
    Seth Willits
  • On 20 okt 2006, at 22.27, Seth Willits wrote:

    > I got it working. I have two and a half gigs of RAM, so that's not
    > an issue.

    Oh, but it can be - you just need to have a large enough application
    (been there, done that...)! Sometimes 32-bit addressing just won't
    cut it!

    I don't know why you would have to tickle it with GDB - That's
    usually not the case.

    > The only thing is that it didn't help me at all. There are three
    > events for the object, the alloc, the autorelease, and the free.
    > The alloc is from the buildParagraphStyle method, the autorelease
    > is from the same, and the release is from the autorelease pool.
    > Despite checking the box to manage retain and release calls, they
    > were not, so I have no more information than when I started. Am I
    > missing something?

    How sure are you that it's actually ever being retained? Can you add
    debug print statements to your code, that includes the pointer
    address of your objects, to be 100% sure that the over-released
    object has actually passed through a code path where it's retained?

    j o a r
  • On Oct 20, 2006, at 2:35 PM, j o a r wrote:

    >> The only thing is that it didn't help me at all. There are three
    >> events for the object, the alloc, the autorelease, and the free.
    >> The alloc is from the buildParagraphStyle method, the autorelease
    >> is from the same, and the release is from the autorelease pool.
    >> Despite checking the box to manage retain and release calls, they
    >> were not, so I have no more information than when I started. Am I
    >> missing something?
    >
    > How sure are you that it's actually ever being retained?

    100% considering it's being put into a dictionary and dictionaries
    retain objects and that's the only location it's being released from.

    > Can you add debug print statements to your code, that includes the
    > pointer address of your objects, to be 100% sure that the over-
    > released object has actually passed through a code path where it's
    > retained?

    There's no question that it's not being retained. I can show you the
    hundreds of thousands of retain messages, but it's also clearly
    *must* happen:

    - (void)setDefaultParagraph:(NSParagraphStyle *)paragraph
    {
        [paragraph retain];
        [defaultParagraph release];
        defaultParagraph = paragraph;
    }

    - (NSParagraphStyle *)buildParagraphStyle:(NSFont *)font;
    {
        NSMutableParagraphStyle * ps = [[[NSMutableParagraphStyle alloc]
    init] autorelease];
        ...
        return ps;
    }

    And defaultParagraph is what's being killed.

    --
    Seth Willits
  • On 21. Oct 2006, at 0:40 , Seth Willits wrote:

    > 100% considering it's being put into a dictionary and dictionaries
    > retain objects and that's the only location it's being released from.

    Hi Seth,

    no idea whether you found it already or not, but this might help you
    in the future:

    http://www.cocoadev.com/index.pl?DebuggingAutorelease

    cheers,
    -k
  • On Oct 23, 2006, at 5:28 PM, Kay Roepke wrote:

    >> 100% considering it's being put into a dictionary and dictionaries
    >> retain objects and that's the only location it's being released from.
    >
    > Hi Seth,
    >
    > no idea whether you found it already or not

    Nope... It still eludes me.

    > but this might help you in the future:
    >
    > http://www.cocoadev.com/index.pl?DebuggingAutorelease

    Well it certainly sounded good!

    "One of the most opaque bugs I've had to deal with in Cocoa is
    leaving a released object in the autorelease pool, causing an
    EXC_BAD_ACCESS in NSPopAutoreleasePool. When this happens, it's
    pretty much impossible to tell what the doubly-released object was
    and where it was instantiated.

    "Fear no more! Using Cocoa's NSZombie debugging class and the command-
    line malloc_history tool, we can nail this bug in a pinch."

    Though I already know what object it is and where it's allocated. I
    just need to find out where it's being released. I can't however just
    put a breakpoint in its release method because it gets sent retain
    and release hundreds of thousands of times in the case where I can
    reproduce the bug, so it'd take forever to step through it. I wish
    there was an easier way of tracking it...

    thanks

    --
    Seth Willits
  • On Oct 23, 2006, at 5:44 PM, Seth Willits wrote:

    > On Oct 23, 2006, at 5:28 PM, Kay Roepke wrote:
    >
    >>> 100% considering it's being put into a dictionary and
    >>> dictionaries retain objects and that's the only location it's
    >>> being released from.
    >>
    >> Hi Seth,
    >>
    >> no idea whether you found it already or not
    >
    > Nope... It still eludes me.
    >
    >
    >> but this might help you in the future:
    >>
    >> http://www.cocoadev.com/index.pl?DebuggingAutorelease
    >
    >
    > Well it certainly sounded good!
    >
    > "One of the most opaque bugs I've had to deal with in Cocoa is
    > leaving a released object in the autorelease pool, causing an
    > EXC_BAD_ACCESS in NSPopAutoreleasePool. When this happens, it's
    > pretty much impossible to tell what the doubly-released object was
    > and where it was instantiated.
    >
    > "Fear no more! Using Cocoa's NSZombie debugging class and the
    > command-line malloc_history tool, we can nail this bug in a pinch."
    >
    >
    > Though I already know what object it is and where it's allocated. I
    > just need to find out where it's being released. I can't however
    > just put a breakpoint in its release method because it gets sent
    > retain and release hundreds of thousands of times in the case where
    > I can reproduce the bug, so it'd take forever to step through it. I
    > wish there was an easier way of tracking it...

    You could probably do a printf on each retain/release and have the
    logging include a stack crawl.
    Once you have that, it'd probably be easy to filter out 99.9% of the
    logging by stripping common patterns in a good text editor.
  • On Oct 23, 2006, at 5:51 PM, John Stiles wrote:

    > You could probably do a printf on each retain/release and have the
    > logging include a stack crawl.

    That's what I want, but how do I get access to the stack? I didn't
    know it was possible!

    --
    Seth Willits
  • __builtin_return_address (x)

    and then a number. Unfortunately x has to be a constant.

    - Chris

    On 24/10/2006, at 11:01 AM, Seth Willits wrote:

    > On Oct 23, 2006, at 5:51 PM, John Stiles wrote:
    >
    >> You could probably do a printf on each retain/release and have the
    >> logging include a stack crawl.
    >
    > That's what I want, but how do I get access to the stack? I didn't
    > know it was possible!
    >
    >
    >
    > --
    > Seth Willits
    >
    >
    >
    > _______________________________________________
    > 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/<chris...>-
    > systems.com
    >
    > This email sent to <chris...>
    >
  • I'd recommend looking for open-source "crash reporter" solutions.
    They will already have solid stack crawl code that you can borrow.

    On Oct 23, 2006, at 6:08 PM, Chris Suter wrote:

    > __builtin_return_address (x)
    >
    > and then a number. Unfortunately x has to be a constant.
    >
    > - Chris
    >
    > On 24/10/2006, at 11:01 AM, Seth Willits wrote:
    >
    >> On Oct 23, 2006, at 5:51 PM, John Stiles wrote:
    >>
    >>> You could probably do a printf on each retain/release and have
    >>> the logging include a stack crawl.
    >>
    >> That's what I want, but how do I get access to the stack? I didn't
    >> know it was possible!
    >>
    >>
    >>
    >> --
    >> Seth Willits
    >>
    >>
    >>
    >> _______________________________________________
    >> 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/<chris...>-
    >> systems.com
    >>
    >> This email sent to <chris...>
    >>
    >
    > _______________________________________________
    > 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/jstiles%
    > 40blizzard.com
    >
    > This email sent to <jstiles...>
  • >> Well it certainly sounded good!
    >>
    >> "Fear no more! Using Cocoa's NSZombie debugging class and the
    >> command-line malloc_history tool, we can nail this bug in a pinch."

    And it is good! Here's what to do:

    1. Run your program.
    2. Pause and break into gdb.
    3. Enable malloc logging by entering the command: "set env MallocStackLoggingNoCompact=1"
    4. Restart your program.
    5. Pause again and turn on NSZombie using "set (BOOL)NSZombieEnabled=1".
    6. Continue execution of your program.
    7. Do the thing that causes the crash.
    8. NSZombie should catch the method being sent to the deallocated object. Note the address of this object.
    9. In the terminal run malloc_history to give you the list of allocations and deallocations for the address you obtained in step 8. Eg: "malloc_history <your_pid> <zombie_address>".
    10. Look at the stack trace for the deallocation of the object of interest.

    I hope that helps.. these are always a pain to debug,

    ~Martin
  • On 23-Oct-06, at 8:44 PM, Seth Willits wrote:

    > Though I already know what object it is and where it's allocated. I
    > just need to find out where it's being released. I can't however
    > just put a breakpoint in its release method because it gets sent
    > retain and release hundreds of thousands of times in the case where
    > I can reproduce the bug, so it'd take forever to step through it.

    This app wouldn't happen to be multi-threaded would it? I ask that
    since it sounds like the problem is hard to reproduce - like a
    typical race condition.

    And maybe you could add code or rearrange code to make it easier to
    catch under gdb - e.g. have some conditional clause that depends on
    the number of iterations and then put a break point in the 'else'
    clause.
    Something like:
    if (numIterations < 200000)
    {
        [myObj release];
    }
    else
    {
        [myObj release];  // add breakpoint here
    }

    --
    Cameron Hayne
    <hayne...>
  • On Oct 23, 2006, at 6:22 PM, Cameron Hayne wrote:

    > On 23-Oct-06, at 8:44 PM, Seth Willits wrote:
    >
    >> Though I already know what object it is and where it's allocated.
    >> I just need to find out where it's being released. I can't however
    >> just put a breakpoint in its release method because it gets sent
    >> retain and release hundreds of thousands of times in the case
    >> where I can reproduce the bug, so it'd take forever to step
    >> through it.
    >
    > This app wouldn't happen to be multi-threaded would it? I ask that
    > since it sounds like the problem is hard to reproduce - like a
    > typical race condition.

    It's not hard to reproduce. I have a 100% repeatable test case.

    > And maybe you could add code or rearrange code to make it easier to
    > catch under gdb - e.g. have some conditional clause that depends on
    > the number of iterations and then put a break point in the 'else'
    > clause.
    > Something like:
    > if (numIterations < 200000)
    > {
    > [myObj release];
    > }
    > else
    > {
    > [myObj release];  // add breakpoint here
    > }

    It would only take one time for it to skip the one case I needed to
    catch it out of hundreds of thousands. It wouldn't be very effective,
    time consuming, and still doesn't guarantee finding anything.

    --
    Seth Willits
  • It just occurred to me to override dealloc instead of release!

    So I did that, and I get a deallocation on this line:

    [attribs
    addEntriesFromDictionary:dictionaryContainingTheNSMutableParagraphStyle]
    ;

    With the stack trace:

    #0    0x00a06558 in -[NSMutableParagraphStyleHACK dealloc] at CodeCog.m:103
    #1    0x9373ec14 in -[NSParagraphStyle release]
    #2    0x907d0a48 in CFDictionarySetValue
    #3    0x929424a4 in -[NSCFDictionary setObject:forKey:]
    #4    0x92952e2c in -[NSMutableDictionary addEntriesFromDictionary:]

    And then sure enough, a little after that:
    *** Selector 'retain' sent to dealloced instance 0x151ac300 of class
    NSMutableParagraphStyleHACK.

    Well that makes it a little more interesting, but still doesn't help
    much because release is always sent then, so the extra release is
    still coming before that.

    <sigh>....

    --
    Seth Willits
  • On Oct 23, 2006, at 6:58 PM, Seth Willits wrote:

    > On Oct 23, 2006, at 6:22 PM, Cameron Hayne wrote:
    >
    >> On 23-Oct-06, at 8:44 PM, Seth Willits wrote:
    >>
    >>> Though I already know what object it is and where it's allocated.
    >>> I just need to find out where it's being released. I can't
    >>> however just put a breakpoint in its release method because it
    >>> gets sent retain and release hundreds of thousands of times in
    >>> the case where I can reproduce the bug, so it'd take forever to
    >>> step through it.
    >>
    >> This app wouldn't happen to be multi-threaded would it? I ask that
    >> since it sounds like the problem is hard to reproduce - like a
    >> typical race condition.
    >
    > It's not hard to reproduce. I have a 100% repeatable test case.

    But I think Cameron is on to something: is your app multi-threaded?
    I've been puzzling over your problem too and have been wondering if
    your problem is related to threads or perhaps even multiple run loops.

    This sounds an awful lot like an autorelease pool is getting released
    and your paragraph style with it. The question is when the
    autorelease pool in question is getting released. Normally, you have
    the autorelease pool that gets released after every run loop
    iteration, and if you're in a multithreaded situation, your threads
    may also have autorelease pools associated with them. You need to
    make sure your object is getting added to the proper autorelease pool
    or it can easily get released out from under you.

    _murat
  • On Oct 23, 2006, at 7:17 PM, Murat Konar wrote:

    >> It's not hard to reproduce. I have a 100% repeatable test case.
    >
    > But I think Cameron is on to something: is your app multi-threaded?
    > I've been puzzling over your problem too and have been wondering if
    > your problem is related to threads or perhaps even multiple run loops.
    >
    > This sounds an awful lot like an autorelease pool is getting
    > released and your paragraph style with it.

    Yes, that's exactly what's happening.

    > The question is when the autorelease pool in question is getting
    > released. Normally, you have the autorelease pool that gets
    > released after every run loop iteration, and if you're in a
    > multithreaded situation, your threads may also have autorelease
    > pools associated with them. You need to make sure your object is
    > getting added to the proper autorelease pool or it can easily get
    > released out from under you.

    Well, there are 4 threads according to the debugger, but I don't
    create any of them and AFAIK they're all just typical background junk
    (because of debugging?).

    Thread 1 is the main thread as expected.

    Thread 2:
      #0  0x9002bbc8 in semaphore_wait_signal_trap
      #1  0x900306ac in pthread_cond_wait
      #2  0x9159a224 in pthreadSemaphoreWait
      #3  0x915994c0 in CMMConvTask
      #4  0x9002b508 in _pthread_body

    Thread 3:
      #0  0x9000ab48 in mach_msg_trap
      #1  0x9000aa9c in mach_msg
      #2  0x907dcb78 in __CFRunLoopRun
      #3  0x907dc47c in CFRunLoopRunSpecific
      #4  0x9298869c in +[NSURLConnection(NSURLConnectionInternal)
    _resourceLoadLoop:]
      #5  0x92961194 in forkThreadForFunction
      #6  0x9002b508 in _pthread_body

    Thread 4:
      #0  0x9001f08c in select
      #1  0x907ef40c in __CFSocketManager
      #2  0x9002b508 in _pthread_body

    There's nothing fancy going on in my code with respect to threads.
    Certainly not at this point.

    Multiple people have said ObjectAlloc *does* watch retain & release
    cycles but despite checking the checkbox to enable that, I don't see
    ObjectAlloc doing it. I'd really like to see if I'm doing something
    wrong here or what.

    --
    Seth Willits
  • It looks like you are initiating, or causing to be initiated, some
    sort of URL loading activity. Are you perchance allocating your
    paragraph style in response to some downloaded information? Does this
    happen on the main thread?Are you  creating any autorelease pools
    yourself?

    Is your singleton class retained? I.e, it's not getting autoreleased,
    and taking your paragraph style with it is it? When is your singleton
    created?

    Since you think you're not doing any work outside the main thread,
    verify that belief by sprinkling your code with assertions to that
    effect:

    #import <pthread.h>
    ...
    NSAssert (pthread_main_np(), @"*** Not on main thread!!!");

    _murat

    p.s. probably unrelated to this problem, but I believe it's not a
    best practice to call methods of an object that hasn't been
    initialized yet. You do this in your singleton's init method.

    On Oct 23, 2006, at 7:41 PM, Seth Willits wrote:

    > On Oct 23, 2006, at 7:17 PM, Murat Konar wrote:
    >
    >>> It's not hard to reproduce. I have a 100% repeatable test case.
    >>
    >> But I think Cameron is on to something: is your app multi-
    >> threaded? I've been puzzling over your problem too and have been
    >> wondering if your problem is related to threads or perhaps even
    >> multiple run loops.
    >>
    >> This sounds an awful lot like an autorelease pool is getting
    >> released and your paragraph style with it.
    >
    > Yes, that's exactly what's happening.
    >
    >
    >> The question is when the autorelease pool in question is getting
    >> released. Normally, you have the autorelease pool that gets
    >> released after every run loop iteration, and if you're in a
    >> multithreaded situation, your threads may also have autorelease
    >> pools associated with them. You need to make sure your object is
    >> getting added to the proper autorelease pool or it can easily get
    >> released out from under you.
    >
    > Well, there are 4 threads according to the debugger, but I don't
    > create any of them and AFAIK they're all just typical background
    > junk (because of debugging?).
    >
    > Thread 1 is the main thread as expected.
    >
    > Thread 2:
    > #0  0x9002bbc8 in semaphore_wait_signal_trap
    > #1  0x900306ac in pthread_cond_wait
    > #2  0x9159a224 in pthreadSemaphoreWait
    > #3  0x915994c0 in CMMConvTask
    > #4  0x9002b508 in _pthread_body
    >
    > Thread 3:
    > #0  0x9000ab48 in mach_msg_trap
    > #1  0x9000aa9c in mach_msg
    > #2  0x907dcb78 in __CFRunLoopRun
    > #3  0x907dc47c in CFRunLoopRunSpecific
    > #4  0x9298869c in +[NSURLConnection(NSURLConnectionInternal)
    > _resourceLoadLoop:]
    > #5  0x92961194 in forkThreadForFunction
    > #6  0x9002b508 in _pthread_body
    >
    > Thread 4:
    > #0  0x9001f08c in select
    > #1  0x907ef40c in __CFSocketManager
    > #2  0x9002b508 in _pthread_body
    >
    >
    > There's nothing fancy going on in my code with respect to threads.
    > Certainly not at this point.
    >
    > Multiple people have said ObjectAlloc *does* watch retain & release
    > cycles but despite checking the checkbox to enable that, I don't
    > see ObjectAlloc doing it. I'd really like to see if I'm doing
    > something wrong here or what.
    >
    >
    > --
    > Seth Willits
    >
    >
    >
    > _______________________________________________
    > 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/<murat...>
    >
    > This email sent to <murat...>
  • I may be waaaay off, but here are two things that helped me squash
    bugs that drove me nuts:

    -Rebuild the nib-file from scratch. Stupid thing to do, but it helped
    at some point, though admittedly this was after I upgraded from
    Panther to Tiger.

    -Implement copyWithZone. If you have a subclass that has some objects
    as ivars, be sure to implement copyWithZone as otherwise the
    implementation of the superclass will be used, which does not retain/
    copy your ivar. However, this ivar may be released with the subclass
    when its implementation of dealloc is called. You may not be using
    copy yourself, but it may be called by the appkit.

    Hope it helps, Patrick
  • Well... I cured the problem. For sure.

    Triggered by a thought Murat Konar had, I "discovered" I was calling
    a relatively private method of a framework that this is all a part
    of, and somehow for whatever reason, I shouldn't have been and that
    was causing the over-release. I would (and really kinda should) step
    through and figure out what the heck is going on, but the private
    method is literally 800+ lines long, so I'd really rather not. Just
    having an 800 line method scares me. I'd hate to have to look at it
    in depth. Isn't that the third thing people don't like to know about?
    Sausage, politics, and big ugly code chunks?

    Anyway, thanks for all the responses. Mission accomplished.

    --
    Seth Willits
  • On 2006-10-23 18:01, Seth Willits said:

    >> You could probably do a printf on each retain/release and have the
    >> logging include a stack crawl.
    >
    > That's what I want, but how do I get access to the stack? I didn't
    > know it was possible!

    <http://developer.apple.com/samplecode/MoreIsBetter/listing42.html>

    Though it looks to be PPC-only still.  :(

    --
    ____________________________________________________________
    Sean McBride, B. Eng                <sean...>
    Rogue Research                        www.rogue-research.com
    Mac Software Developer              Montréal, Québec, Canada
previous month october 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 31          
Go to today