Debugging a CALayer Bad Access

  • Debugging is not my strong suit.  I usually rely on console messages, stack
    trace, logic, isolation, trial and error.

    I have several types (nibs) of document windows, only one of which can be
    used at a time.  Switching involves closing one and opening another.  After
    realizing that the closed windows were not deallocating, I made sure all my
    iBOutlets were weak.  The good news is that they now deallocate.  The bad
    news is that they crash with ³bad access² and no console messages. The
    windows all contain basically the same content.  Their main view has a
    rather complex tree of CALayers, some custom, some not.  The stack trace
    shows that during window deallocate, the bad access is on ³actionForKey² for
    some layer.  I overrode this (calling super) in the custom layers, but no
    joy in identifying the problem.

    Is there a better way to trap this, so I can find out where it is coming
    from?
  • On May 30, 2013, at 10:40 AM, Gordon Apple <ga...> wrote:

    > I have several types (nibs) of document windows, only one of which can be used at a time.  Switching involves closing one and opening another.  After realizing that the closed windows were not deallocating, I made sure all my iBOutlets were weak.  The good news is that they now deallocate.  The bad news is that they crash with “bad access” and no console messages.

    Look up the docs for NSZombieEnabled. You can turn this on from the scheme settings in Xcode 4.

    —Jens
  • Jens's advice is good in all cases, but I want to comment on how to pursue your particular issue (assuming I understand it correctly).

    On 30 May 2013, at 12:40 PM, Gordon Apple <ga...> wrote:

    > Debugging is not my strong suit.  I usually rely on console messages, stack trace, logic, isolation, trial and error.

    (Not using the debugger _at all?_)

    Make it your strong suit. Most of your techniques are perfectly valid, and easier to do with a debugger, but the generally accepted term for "trial and error" is "blind thrashing." I have no confidence that shotgunning weak pointers at your memory management will give you a robust solution.

    > I have several types (nibs) of document windows, only one of which can be used at a time.  Switching involves closing one and opening another.  After realizing that the closed windows were not deallocating

    How are you closing them? If it's by -orderOut:, failing to release is the expected behavior.

    If it's by -close or -performClose:, the expected behavior is _usually_ to release the window, but sometimes not. Read the documentation for -close (both NSWindowController and NSWindow), -performClose:, -orderOut:, -isReleasedWhenClosed, and -setReleasedWhenClosed:. Also, Xcode's XIB templates sometimes set Release When Closed (checkbox in the window's attributes inspector), sometimes not, thus overriding the default behavior. Audit your XIBs.

    Note that if the window NIB is loaded by an NSWindowController, Released When Closed is ignored; deallocating the controller deallocates the window. Search the documentation for "Managing Nib Objects in OS X".

    > After realizing that the closed windows were not deallocating, I made sure all my iBOutlets were weak.

    All your IBOutlets to what? From what? _Some_ references could be weak if you'd like them to be. I guess it's possible that throwing "weak" at _all_ your references would do no harm, but I don't think it's the way to bet. AppKit is supposed to do the right thing without extraordinary workarounds. Research and analyze first; work from principles. If you have 10 outlets, you'd have to try-and-err 512 times on the average. (If you're not lucky, you'll hit on an _apparent_ solution early, only to crash, perhaps more subtly, in the future.)

    > The bad news is that they crash with “bad access” and no console messages.

    The debugger would give you better console messages, even if you're not interested in tools that provide more and better information than console messages.

    And as Jens said, debug (set Enable Zombie Objects in the Diagnostics tab of the Run action in the Scheme editor) or profile (one of the options in the Allocations instrument) using zombie detection.

    — F

    --
    Fritz Anderson
    Xcode 4 Unleashed: 4.5 supplement for free!
    http://www.informit.com/store/xcode-4-unleashed-9780672333279
  • Sorry for the delay.  I¹ve been digesting your comments and trying to get
    more familiar with Instruments.  I¹m mainly closing windows via ³close² in
    the window controller.  I did get a little over zealous on the weak outlets.
    Outlets to UI elements should probably always be weak, but outlets from the
    nib owner to top-level elements should mostly be strong.  NSNib allows you
    to get a list of top-level elements, which can be retained individually or
    by the returned array, but window controllers don¹t give you that, so you
    have to make them explicit.

    Because I typically split my controllers (included in the nib), according to
    function, I don¹t often use ³awakeFromNib² due to unredictability of order.
    Instead, I use my own ³wakeUp² routine (called from the window controller)
    so I can guarantee the order.  There may be a similar issue in dealloc.

    On 5/30/13 2:39 PM, "Fritz Anderson" <fritza...> wrote:

    > Jens's advice is good in all cases, but I want to comment on how to pursue
    > your particular issue (assuming I understand it correctly).
    >
    > On 30 May 2013, at 12:40 PM, Gordon Apple <ga...> wrote:
    >
    >>> Debugging is not my strong suit.  I usually rely on console messages, stack
    >> trace, logic, isolation, trial and error.
    >
    > (Not using the debugger _at all?_)
    >
    > Make it your strong suit. Most of your techniques are perfectly valid, and
    > easier to do with a debugger, but the generally accepted term for "trial and
    > error" is "blind thrashing." I have no confidence that shotgunning weak
    > pointers at your memory management will give you a robust solution.
    >
    >>> I have several types (nibs) of document windows, only one of which can be
    >> used at a time.  Switching involves closing one and opening another.  After
    >> realizing that the closed windows were not deallocating
    >
    > How are you closing them? If it's by -orderOut:, failing to release is the
    > expected behavior.
    >
    > If it's by -close or -performClose:, the expected behavior is _usually_ to
    > release the window, but sometimes not. Read the documentation for -close (both
    > NSWindowController and NSWindow), -performClose:, -orderOut:,
    > -isReleasedWhenClosed, and -setReleasedWhenClosed:. Also, Xcode's XIB
    > templates sometimes set Release When Closed (checkbox in the window's
    > attributes inspector), sometimes not, thus overriding the default behavior.
    > Audit your XIBs.
    >
    > Note that if the window NIB is loaded by an NSWindowController, Released When
    > Closed is ignored; deallocating the controller deallocates the window. Search
    > the documentation for "Managing Nib Objects in OS X".
    >
    >>> After realizing that the closed windows were not deallocating, I made sure
    >> all my iBOutlets were weak.
    >
    > All your IBOutlets to what? From what? _Some_ references could be weak if
    > you'd like them to be. I guess it's possible that throwing "weak" at _all_
    > your references would do no harm, but I don't think it's the way to bet.
    > AppKit is supposed to do the right thing without extraordinary workarounds.
    > Research and analyze first; work from principles. If you have 10 outlets,
    > you'd have to try-and-err 512 times on the average. (If you're not lucky,
    > you'll hit on an _apparent_ solution early, only to crash, perhaps more
    > subtly, in the future.)
    >
    >>> The bad news is that they crash with ³bad access² and no console messages.
    >
    > The debugger would give you better console messages, even if you're not
    > interested in tools that provide more and better information than console
    > messages.
    >
    > And as Jens said, debug (set Enable Zombie Objects in the Diagnostics tab of
    > the Run action in the Scheme editor) or profile (one of the options in the
    > Allocations instrument) using zombie detection.
    >
    > ‹ F

    --
    Gordon Apple
    Ed4U
    Little Rock, AR
previous month may 2013 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