Tracking down SIGABRTs

  • I've had the joy of trying to reassemble my app which a co worker improved last week by moving it to storyboarding.  What's popping up every now and then as I try to wire views together are instant SIGABRTs with no indication why this is happening.

    I'm currently stuck going from a TableViewController to another TableViewController and as soon as any TVC loads (even an empty one, even the same one), BLAM.

    The project is based off of the Tabbed Application template, has 4 tabs and all views work fine except one which has a Navigation controller that goes off to a TVC with a Nav bar at the top.  When I try to nav to another TVC, as soon as it finishes displaying, (even with the same or an empty TVC), a SIGABRT happens.

    I've checked the table cell names, rebuilt the screen, checked Apple's samples and Ray W's book, been at this all day, to no avail.

    So, the big question is when a SIGABRT happens, how do each of you go about tracking it down?
  • On Sun, Apr 29, 2012 at 7:50 PM, Alex Zavatone <zav...> wrote:
    > I've had the joy of trying to reassemble my app which a co worker improved last week by moving it to storyboarding.  What's popping up every now and then as I try to wire views together are instant SIGABRTs with no indication why this is happening.

    Place some assertions as the very first executable lines in each of
    your subroutines.  The chances are quite good that the cause of the
    SIGABRTs are executable quite a long time before the crashes actually
    happen.

    When you fix your (or his!) bugs, leave the assertions in.  You'll
    find out about many new bugs right away.

    #include <assert.h>

    void foo( int *ptr )
    {
      assert( NULL != ptr );
    ...
      return;
    }

    assertions are a lot better than comments for documenting routine
    parameters because they cannot be ignored, and must be updated when
    the acceptable ranges of parameters are revised.

    You can also assert the ranges of return results, but my experience is
    that I get more mileage out of asserting input parameters.

    --
    Don Quixote de la Mancha
    Dulcinea Technologies Corporation
    Software of Elegance and Beauty
    http://www.dulcineatech.com
    <quixote...>
  • It sounds to me like your xib (nib) file has been "corrupted". For example, it's possible that you have somehow destroyed, say, a link between an object (view?) and its counterpart in your implementation or a link between an object like a button or a textfield and it's IBAction.

    I suggest that you check your xib thoroughly.

    On Apr 29, 2012, at 10:50 PM, Alex Zavatone wrote:

    > I've had the joy of trying to reassemble my app which a co worker improved last week by moving it to storyboarding.  What's popping up every now and then as I try to wire views together are instant SIGABRTs with no indication why this is happening.
    >
    > I'm currently stuck going from a TableViewController to another TableViewController and as soon as any TVC loads (even an empty one, even the same one), BLAM.
    >
    > The project is based off of the Tabbed Application template, has 4 tabs and all views work fine except one which has a Navigation controller that goes off to a TVC with a Nav bar at the top.  When I try to nav to another TVC, as soon as it finishes displaying, (even with the same or an empty TVC), a SIGABRT happens.
    >
    > I've checked the table cell names, rebuilt the screen, checked Apple's samples and Ray W's book, been at this all day, to no avail.
    >
    > So, the big question is when a SIGABRT happens, how do each of you go about tracking it down?

    Charlie Dickman
    <3tothe4th...>
  • I had the same thing Friday night or last night too.

    I ended up creating a new TVC, moving pieces in one at a time and in one case, it was the table cell name not matching.

    Now, I've gotten an empty TVC to work, so it's move the pieces in one at a time again.

    There are no errors when I profile the app and generally, I've seen SIGABRTs when I make a type and call a selector that doesn't exist or forget to wire up something I didn't know I need to wire.

    It's these types of "missing connections" I'm wondering if there are elegant ways to catch or trap for.

    In many ways, storyboarding is more difficult than programming, because you often can't see and don't know what needs to be hooked up or is not wired up properly.  Some nice visual graphical  hierarchy of all the required parts and connections that are required to work would be nice because that would show in one place all the connections and objects that are required and if they are properly hooked up.

    It just seems (I could be wrong) that storyboarding can be nice and graphical but really easy to screw up and often very hard and time consuming to figure out why.  I've been at reassembling my app since Friday and it's not terribly complicated.  Trial by fire I guess.

    On Apr 29, 2012, at 11:00 PM, Charlie Dickman wrote:

    > It sounds to me like your xib (nib) file has been "corrupted". For example, it's possible that you have somehow destroyed, say, a link between an object (view?) and its counterpart in your implementation or a link between an object like a button or a textfield and it's IBAction.
    >
    > I suggest that you check your xib thoroughly.
    >
    > On Apr 29, 2012, at 10:50 PM, Alex Zavatone wrote:
    >
    >> I've had the joy of trying to reassemble my app which a co worker improved last week by moving it to storyboarding.  What's popping up every now and then as I try to wire views together are instant SIGABRTs with no indication why this is happening.
    >>
    >> I'm currently stuck going from a TableViewController to another TableViewController and as soon as any TVC loads (even an empty one, even the same one), BLAM.
    >>
    >> The project is based off of the Tabbed Application template, has 4 tabs and all views work fine except one which has a Navigation controller that goes off to a TVC with a Nav bar at the top.  When I try to nav to another TVC, as soon as it finishes displaying, (even with the same or an empty TVC), a SIGABRT happens.
    >>
    >> I've checked the table cell names, rebuilt the screen, checked Apple's samples and Ray W's book, been at this all day, to no avail.
    >>
    >> So, the big question is when a SIGABRT happens, how do each of you go about tracking it down?
    >
    > Charlie Dickman
    > <3tothe4th...>
    >
    >
    >
  • At least during development I do this to main.m

    int main(int argc, char *argv[])
    {
    @autoreleasepool {
      @try
      {
      return UIApplicationMain(argc, argv, nil, NSStringFromClass([HIPAppDelegate class]));
      }
      @catch (NSException *exception)
      {
      NSLog( @"Exception in main %@\n%@", [ exception description ], [ exception callStackSymbols ] );
      }
    }
    }

    I find that catches some places I would otherwise get untrackable SIGABRTs.

    On Apr 30, 2012, at 11:18 AM, Alex Zavatone wrote:

    > I had the same thing Friday night or last night too.
    >
    > I ended up creating a new TVC, moving pieces in one at a time and in one case, it was the table cell name not matching.
    >
    > Now, I've gotten an empty TVC to work, so it's move the pieces in one at a time again.
    >
    > There are no errors when I profile the app and generally, I've seen SIGABRTs when I make a type and call a selector that doesn't exist or forget to wire up something I didn't know I need to wire.
    >
    > It's these types of "missing connections" I'm wondering if there are elegant ways to catch or trap for.
    >
    > In many ways, storyboarding is more difficult than programming, because you often can't see and don't know what needs to be hooked up or is not wired up properly.  Some nice visual graphical  hierarchy of all the required parts and connections that are required to work would be nice because that would show in one place all the connections and objects that are required and if they are properly hooked up.
    >
    > It just seems (I could be wrong) that storyboarding can be nice and graphical but really easy to screw up and often very hard and time consuming to figure out why.  I've been at reassembling my app since Friday and it's not terribly complicated.  Trial by fire I guess.
    >
    >
    > On Apr 29, 2012, at 11:00 PM, Charlie Dickman wrote:
    >
    >> It sounds to me like your xib (nib) file has been "corrupted". For example, it's possible that you have somehow destroyed, say, a link between an object (view?) and its counterpart in your implementation or a link between an object like a button or a textfield and it's IBAction.
    >>
    >> I suggest that you check your xib thoroughly.
    >>
    >> On Apr 29, 2012, at 10:50 PM, Alex Zavatone wrote:
    >>
    >>> I've had the joy of trying to reassemble my app which a co worker improved last week by moving it to storyboarding.  What's popping up every now and then as I try to wire views together are instant SIGABRTs with no indication why this is happening.
    >>>
    >>> I'm currently stuck going from a TableViewController to another TableViewController and as soon as any TVC loads (even an empty one, even the same one), BLAM.
    >>>
    >>> The project is based off of the Tabbed Application template, has 4 tabs and all views work fine except one which has a Navigation controller that goes off to a TVC with a Nav bar at the top.  When I try to nav to another TVC, as soon as it finishes displaying, (even with the same or an empty TVC), a SIGABRT happens.
    >>>
    >>> I've checked the table cell names, rebuilt the screen, checked Apple's samples and Ray W's book, been at this all day, to no avail.
    >>>
    >>> So, the big question is when a SIGABRT happens, how do each of you go about tracking it down?
    >>
    >> Charlie Dickman
    >> <3tothe4th...>
    >>
    >>
    >>

  • On Apr 29, 2012, at 11:26 PM, Roland King wrote:

    > At least during development I do this to main.m
    >
    > int main(int argc, char *argv[])
    > {
    > @autoreleasepool {
    > @try
    > {
    > return UIApplicationMain(argc, argv, nil, NSStringFromClass([HIPAppDelegate class]));
    > }
    > @catch (NSException *exception)
    > {
    > NSLog( @"Exception in main %@\n%@", [ exception description ], [ exception callStackSymbols ] );
    > }
    > }
    > }

    Awesome.  What's the renaming of AppDelegate? HIPAppDelegate
  • That's autogenerated code, came from the project template.

    On Apr 30, 2012, at 11:33 AM, Alex Zavatone wrote:

    >
    > On Apr 29, 2012, at 11:26 PM, Roland King wrote:
    >
    >> At least during development I do this to main.m
    >>
    >> int main(int argc, char *argv[])
    >> {
    >> @autoreleasepool {
    >> @try
    >> {
    >> return UIApplicationMain(argc, argv, nil, NSStringFromClass([HIPAppDelegate class]));
    >> }
    >> @catch (NSException *exception)
    >> {
    >> NSLog( @"Exception in main %@\n%@", [ exception description ], [ exception callStackSymbols ] );
    >> }
    >> }
    >> }
    >
    > Awesome.  What's the renaming of AppDelegate? HIPAppDelegate
    >
  • Ahh.  Well, I changed it back from HIPAppDelegate to AppDelegate and when the SIGABRT happens, the catch isn't catching it.  I set a breakpoint on NSLog and it's never triggered.

    Am I assuming too much here?

    On Apr 29, 2012, at 11:35 PM, Roland King wrote:

    > That's autogenerated code, came from the project template.
    >
    >
    > On Apr 30, 2012, at 11:33 AM, Alex Zavatone wrote:
    >
    >>
    >> On Apr 29, 2012, at 11:26 PM, Roland King wrote:
    >>
    >>> At least during development I do this to main.m
    >>>
    >>> int main(int argc, char *argv[])
    >>> {
    >>> @autoreleasepool {
    >>> @try
    >>> {
    >>> return UIApplicationMain(argc, argv, nil, NSStringFromClass([HIPAppDelegate class]));
    >>> }
    >>> @catch (NSException *exception)
    >>> {
    >>> NSLog( @"Exception in main %@\n%@", [ exception description ], [ exception callStackSymbols ] );
    >>> }
    >>> }
    >>> }
    >>
    >> Awesome.  What's the renaming of AppDelegate? HIPAppDelegate
    >>
    >
  • On Sun, Apr 29, 2012 at 8:00 PM, Don Quixote de la Mancha
    <quixote...> wrote:
    > Place some assertions as the very first executable lines in each of
    > your subroutines.  The chances are quite good that the cause of the
    > SIGABRTs are executable quite a long time before the crashes actually
    > happen.
    ...
    > #include <assert.h>
    >
    > void foo( int *ptr )
    > {
    >   assert( NULL != ptr );
    > ...
    >   return;
    > }

    While asserting that a pointer which must not be NULL actually isn't
    NULL, that's quite a permissive test and does not help at all for
    pointers which may be NULL.

    A pointer may be given an invalid value quite a long time before it
    causes a problem, and a value may initially be valid only to become
    invalid much later when the heap block it points to (or points into
    the middle of) is disposed.

    A stricter test is to actually dereference the pointer by reading from
    it.  It's best to read in the entire block that it points to, if you
    know it's type.  While less strict, far quicker and easier is to cast
    it to a char or unsigned char then read that:

    BOOL checkPointer( void const *p )
    {
        unsigned char val = *(unsigned char*)p;

        return TRUE;
    }

    You'll see that that test always returns true, but if your pointer
    points into unmapped memory, you will get a crash right there.

    I have a bunch of these kinds of tests in libmdc:

      http://www.goingware.com/libmdc/

    While libmdc is mostly C++ templates, even if you don't know C++ the
    code is so straightforwad it should be easy to figure out for anyone
    who knows any "Curly Brace" language.

    Even if the memory is mapped, if you run your app under Guard Malloc
    or Valgrind, reads of memory which is mapped but not allocated in some
    way will cause a crash.

    Your pointer may point into memory which is mapped but read-only, such
    as executable code or read-only memory mapped data.  In that case, IF
    YOU CAN BE SURE ONLY ONE THREAD IS ACCESSING THAT DATA! read in a byte
    to save its original value, write a value into the pointer, then
    restore the original value:

    BOOL checkWriteablePointer( void *p ) // NOT const pointer!
    {
        unsigned char save = *(unsigned char*)p;
      *(unsigned char*)p = 0xbe;
      *(unsigned char*)p = save;

        return TRUE;
    }

    Even if it's a const pointer, but you can be sure that the underlying
    memory that is storing the value is itself writeable, you can cast a
    const pointer to a non-const one.  For C++ or Objective-C++ you should
    use const_cast to make it clearer what you are doing.

    If your pointer claims to point to any particular kind of object, then
    verify that it really does point to that kind of object!  For C++ use
    dynamic_cast, for Objective-C use class and isKindOfClass.  There's a
    real good discussion of that at StackOverflow:

      http://stackoverflow.com/questions/1374168/is-there-an-equivalent-to-cs-dyn
    amic-cast-in-objective-c


    While to the best of my knowledge it's not actually enforced either by
    the compiler or the runtime, the convention in Objective-C is that
    non-nil id pointers MUST point to Objective-C OBJECTS and not just to
    any kind of data, even if they point to completely valid memory.

    You can enforce this by calling some method which is in the base class
    NSObject then asserting you got some rational result, or for general
    (not Cocoa or Cocoa Touch) Objective-C Object.

    --
    Don Quixote de la Mancha
    Dulcinea Technologies Corporation
    Software of Elegance and Beauty
    http://www.dulcineatech.com
    <quixote...>
  • Ray Wenderlich's website has a guide on tracking down SIGABRTs, it might
    help. It's a two part guide, for the second part just change the "1" at the
    end of the link to "2"

    http://www.raywenderlich.com/10209/my-app-crashed-now-what-part-1

    On Mon, Apr 30, 2012 at 05:50, Alex Zavatone <zav...> wrote:

    > I've had the joy of trying to reassemble my app which a co worker improved
    > last week by moving it to storyboarding.  What's popping up every now and
    > then as I try to wire views together are instant SIGABRTs with no
    > indication why this is happening.
    >
    > I'm currently stuck going from a TableViewController to another
    > TableViewController and as soon as any TVC loads (even an empty one, even
    > the same one), BLAM.
    >
    > The project is based off of the Tabbed Application template, has 4 tabs
    > and all views work fine except one which has a Navigation controller that
    > goes off to a TVC with a Nav bar at the top.  When I try to nav to another
    > TVC, as soon as it finishes displaying, (even with the same or an empty
    > TVC), a SIGABRT happens.
    >
    > I've checked the table cell names, rebuilt the screen, checked Apple's
    > samples and Ray W's book, been at this all day, to no avail.
    >
    > So, the big question is when a SIGABRT happens, how do each of you go
    > about tracking it down?
    >
  • On Apr 29, 2012, at 7:50 PM, Alex Zavatone wrote:

    > I've had the joy of trying to reassemble my app which a co worker improved last week by moving it to storyboarding.  What's popping up every now and then as I try to wire views together are instant SIGABRTs with no indication why this is happening.

    Are you asking how to catch these in the debugger to get a backtrace? If the debugger doesn’t already stop on these, try adding a symbolic breakpoint on the function abort().

    —Jens
  • On Apr 29, 2012, at 8:00 PM, Don Quixote de la Mancha wrote:

    > Place some assertions as the very first executable lines in each of
    > your subroutines.
    ...
    > #include <assert.h>
    >
    > void foo( int *ptr )
    > {
    > assert( NULL != ptr );

    Ouch. Don’t use this in a Cocoa app; use NSAssert and NSParameterAssert instead. You’ll get much better reporting of the error, because you can use custom messages with parameters, and the app will raise an exception and log the backtrace. On Mac OS the system will also put up the standard crash alert, whereas a call to abort() (which is what assert() calls) just makes the app vanish with no explanation to the user.

    —Jens
  • >> void foo( int *ptr )
    >> {
    >> assert( NULL != ptr );
    >
    > Ouch. Don't use this in a Cocoa app; use NSAssert and NSParameterAssert
    > instead. You'll get much better reporting of the error, because you can
    > use custom messages with parameters, and the app will raise an exception
    > and log the backtrace. On Mac OS the system will also put up the
    > standard crash alert, whereas a call to abort() (which is what assert()
    > calls) just makes the app vanish with no explanation to the user.

    Depends on when and why you use asserts.  If you use them only to assert impossibilities and programmer errors, I find assert()'s behaviour nice.  And you can stub them entirely in release, meaning the user never sees them anyway.

    Sean
  • On Apr 30, 2012, at 11:00 AM, Jens Alfke <jens...> wrote:
    > On Apr 29, 2012, at 8:00 PM, Don Quixote de la Mancha wrote:
    >> Place some assertions as the very first executable lines in each of
    >> your subroutines.
    > ...
    >> #include <assert.h>
    >>
    >> void foo( int *ptr )
    >> {
    >> assert( NULL != ptr );
    >
    > Ouch. Don’t use this in a Cocoa app; use NSAssert and NSParameterAssert instead. You’ll get much better reporting of the error, because you can use custom messages with parameters, and the app will raise an exception and log the backtrace. On Mac OS the system will also put up the standard crash alert, whereas a call to abort() (which is what assert() calls) just makes the app vanish with no explanation to the user.

    assert() and abort() also log the backtrace and present the standard crash alert to the user.

    --
    Greg Parker    <gparker...>    Runtime Wrangler
  • On Apr 30, 2012, at 12:00 PM, Jens Alfke wrote:

    > On Mac OS the system will also put up the standard crash alert, whereas a call to abort() (which is what assert() calls) just makes the app vanish with no explanation to the user.

    Depends on the version perhaps? I certainly see abort() putting up the "The application has unexpectedly quit" dialog.

    --
    Scott Ribe
    <scott_ribe...>
    http://www.elevated-dev.com/
    (303) 722-0567 voice
previous month april 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            
Go to today