Debugging -setNeedsDisplayInRect:

  • I've got a view that, according to Quartz Debug, is invalidating a large and unnecessary portion of the view when certain user events happen.

    The problem is, I have no idea what is causing this to happen. What strategies are best for debugging the -setNeedsDisplayInRect: method to find out specifically who is calling it where and with what frame?

    I can't put a symbolic breakpoint on the method, because it gets called very often, including when the app is activated, which causes Xcode to reactivate itself and get in the way. I then changed the breakpoint to auto-continue and just print the stack trace each time the method is called, but now I feel like I'm looking for a needle within a huge console log. I really need it to break when the rect is of a certain size, but the NSRect data structure is more than twice as large as a CPU register on x86_64, so the structure is placed on the stack, but how do I break on a variable buried within the stack?

    Nick Zitzmann
    <http://www.chronosnet.com/>
  • On 7/27/12 5:10 AM, Nick Zitzmann wrote:
    > I've got a view that, according to Quartz Debug, is invalidating a large and
    > unnecessary portion of the view when certain user events happen.
    >
    > The problem is, I have no idea what is causing this to happen. What
    > strategies are best for debugging the -setNeedsDisplayInRect: method to find
    > out specifically who is calling it where and with what frame?
    >
    > I can't put a symbolic breakpoint on the method, because it gets called very
    > often, including when the app is activated, which causes Xcode to reactivate
    > itself and get in the way. I then changed the breakpoint to auto-continue and
    > just print the stack trace each time the method is called, but now I feel
    > like I'm looking for a needle within a huge console log. I really need it to
    > break when the rect is of a certain size, but the NSRect data structure is
    > more than twice as large as a CPU register on x86_64, so the structure is
    > placed on the stack, but how do I break on a variable buried within the
    > stack?

    Why not overwrite -setNeedsDisplayInRect: put a little if logic to determine if
    that's a size you would like to have more info on, add a NSLog() inside and put
    your breakpoint on the NSLog() call?

    Regards
    Markus
    --
    __________________________________________
    Markus Spoettl
  • On Jul 27, 2012, at 2:35 AM, Markus Spoettl <ms_lists...> wrote:

    > On 7/27/12 5:10 AM, Nick Zitzmann wrote:
    >> I've got a view that, according to Quartz Debug, is invalidating a large and
    >> unnecessary portion of the view when certain user events happen.
    >>
    >> The problem is, I have no idea what is causing this to happen. What
    >> strategies are best for debugging the -setNeedsDisplayInRect: method to find
    >> out specifically who is calling it where and with what frame?
    >>
    >> I can't put a symbolic breakpoint on the method, because it gets called very
    >> often, including when the app is activated, which causes Xcode to reactivate
    >> itself and get in the way. I then changed the breakpoint to auto-continue and
    >> just print the stack trace each time the method is called, but now I feel
    >> like I'm looking for a needle within a huge console log. I really need it to
    >> break when the rect is of a certain size, but the NSRect data structure is
    >> more than twice as large as a CPU register on x86_64, so the structure is
    >> placed on the stack, but how do I break on a variable buried within the
    >> stack?
    >
    > Why not overwrite -setNeedsDisplayInRect: put a little if logic to determine if that's a size you would like to have more info on, add a NSLog() inside and put your breakpoint on the NSLog() call?

    But I need to be able to see **all** invocations of the method from **all** NSViews to catch the culprit, because I have a rather complicated view hierarchy, including some views for which I don't have the source, and I don't know exactly which view is doing this. In order to do that, I need to set a conditional breakpoint, and this would be easy if an NSRect could be stored in a register, but how do I set a conditional breakpoint when the variable I want to investigate is on the stack? And where would I find each of the CGFloats on the stack?

    Nick Zitzmann
    <http://www.chronosnet.com/>
  • On Jul 27, 2012, at 8:55 AM, Nick Zitzmann <nick...> wrote:

    > But I need to be able to see **all** invocations of the method from **all** NSViews to catch the culprit, because I have a rather complicated view hierarchy, including some views for which I don't have the source, and I don't know exactly which view is doing this. In order to do that, I need to set a conditional breakpoint, and this would be easy if an NSRect could be stored in a register, but how do I set a conditional breakpoint when the variable I want to investigate is on the stack? And where would I find each of the CGFloats on the stack?

    For debugging, you might consider swizzling NSView's -setNeedsDisplayInRect: to do the conditional logging that Markus suggested.

    Cheers,

    Curt
    -----------------------------------------------------------------------------
    Curt Clifton, PhD
    Software Engineer
    The Omni Group
    www.curtclifton.net
  • On Fri, Jul 27, 2012, at 08:55 AM, Nick Zitzmann wrote:
    > But I need to be able to see **all** invocations of the method from
    > **all** NSViews to catch the culprit, because I have a rather complicated
    > view hierarchy, including some views for which I don't have the source,
    > and I don't know exactly which view is doing this. In order to do that, I
    > need to set a conditional breakpoint, and this would be easy if an NSRect
    > could be stored in a register, but how do I set a conditional breakpoint
    > when the variable I want to investigate is on the stack? And where would
    > I find each of the CGFloats on the stack?

    The easiest thing to do is what Curt recommended, which lets the
    compiler deal with the ABI for you.

    But if you really want to learn about how arguments are passed on x86-64
    (especially useful if you're already in the debugger or are reading
    disassembly), download the AMD64 Application Binary Interface from
    <http://www.x86-64.org/documentation.html>. You specifically want to
    look at Section 3.2, Function Calling Sequence. That'll tell you
    everything you need to know about how the stack frame is set up
    (including what registers point to the base and the top of the current
    frame), as well as where arguments of different types will end up (in
    integer or XMM registers or on the stack).

    --Kyle Sluder
  • On Jul 27, 2012, at 10:36 AM, Curt Clifton <curt.clifton...> wrote:

    > On Jul 27, 2012, at 8:55 AM, Nick Zitzmann <nick...> wrote:
    >
    >> But I need to be able to see **all** invocations of the method from **all** NSViews to catch the culprit, because I have a rather complicated view hierarchy, including some views for which I don't have the source, and I don't know exactly which view is doing this. In order to do that, I need to set a conditional breakpoint, and this would be easy if an NSRect could be stored in a register, but how do I set a conditional breakpoint when the variable I want to investigate is on the stack? And where would I find each of the CGFloats on the stack?
    >
    > For debugging, you might consider swizzling NSView's -setNeedsDisplayInRect: to do the conditional logging that Markus suggested.

    I usually don't like swizzling; it feels like black magic to me. But since it was just for debugging, this time I put on my blue robe and pointy yellow wizard hat anyway, and found and fixed the problem. Thanks.

    Nick Zitzmann
    <http://www.chronosnet.com/>
previous month july 2012 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