file scan results in EX_BAD_ACCESS

  • Hi All,

    I am trying to parse a large file without approximately 300,000 lines
    of text. Judging from the console print, the method does go through
    all the records, but then the program seems to freeze with a message
    "Loading 87348  stack frames", and when I hit cancel to that alert, I
    get the EX_BAD_ACCESS error. Because of the way the debugger freezes
    (and because it would take years to load 87000 stack frames), I'm
    having a terrible time tracing the error.

    Critical portions of code below. Thanks for the help.

    Daniel

    (in main)

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    DataParser *dp = [DataParser parserWithRecordDelim: @"\r"];
    NSString *path, *fullPath, *fileName;
    NSFileManager *NSFm;
    NSMutableArray *theData;

    fileName = @"cleaner data.txt";
    NSFm = [NSFileManager defaultManager];
    path = @"/Users/danielchild/Documents/DATA/";
    fullPath = [path stringByAppendingPathComponent: fileName];

    theData = [dp parseFileAtPath: fullPath];
    [pool release];

    return 0;

    The parser is created as follows:

    + (DataParser *) parserWithRecordDelim: (NSString *) rd
    {
      DataParser *dp = [[[DataParser alloc] init] autorelease];
      [dp setRecordDelim: rd];
      return dp;
    }

    And the parse file method is this:

    - (NSMutableArray *) parseFileAtPath: (NSString *) path
    {
      NSString *fileAsString, *oneRecord;
      NSMutableArray *unparsedRecords = [[[NSMutableArray alloc] init]
    autorelease];

      fileAsString = [NSString stringWithContentsOfFile: path];
      NSScanner *scanner = [NSScanner scannerWithString: fileAsString];
      while (![scanner isAtEnd])
      {
        if ([scanner scanUpToString:recordDelim intoString: &oneRecord])
        {
          [unparsedRecords addObject: oneRecord];
          printf("%s\n", [oneRecord cString]);
        }
      }
      return unparsedRecords;
    }
  • On 8/31/07, Daniel Child <wchild...> wrote:
    > Hi All,
    >
    > I am trying to parse a large file without approximately 300,000 lines
    > of text. Judging from the console print, the method does go through
    > all the records, but then the program seems to freeze with a message
    > "Loading 87348  stack frames", and when I hit cancel to that alert, I
    > get the EX_BAD_ACCESS error. Because of the way the debugger freezes
    > (and because it would take years to load 87000 stack frames), I'm
    > having a terrible time tracing the error.
    >
    > Critical portions of code below. Thanks for the help.

    You appear to have an infinite recursion problem. I don't spot an
    obvious source of it in the code you submitted so far.

    -Shawn
  • On Aug 31, 2007, at 1:38 PM, Daniel Child wrote:

    > Because of the way the debugger freezes (and because it would take
    > years to load 87000 stack frames), I'm having a terrible time
    > tracing the error.

    Perhaps try starting the app in the terminal from gdb? Then, when it
    crashes, run "backtrace 50" to get the last 50 stack frames. This may
    avoid having to parse the entire stack. You might even be able to get
    the outermost stack frames by specifying -50.

    --
    Mike Blaguszewski / Cocoa Hacker / Ambrosia Software, Inc.
  • The only code that gets called is what you saw, however. I'm
    wondering if it has something to do with the memory not being released.

    Is there a list of the meaning of the various SIG DEV errors? At one
    point I think SIGDEV 11 was issued.

    On Aug 31, 2007, at 1:48 PM, Shawn Erickson wrote:

    > On 8/31/07, Daniel Child <wchild...> wrote:
    >> Hi All,
    >>
    >> I am trying to parse a large file without approximately 300,000 lines
    >> of text. Judging from the console print, the method does go through
    >> all the records, but then the program seems to freeze with a message
    >> "Loading 87348  stack frames", and when I hit cancel to that alert, I
    >> get the EX_BAD_ACCESS error. Because of the way the debugger freezes
    >> (and because it would take years to load 87000 stack frames), I'm
    >> having a terrible time tracing the error.
    >>
    >> Critical portions of code below. Thanks for the help.
    >
    > You appear to have an infinite recursion problem. I don't spot an
    > obvious source of it in the code you submitted so far.
    >
    > -Shawn
  • On Aug 31, 2007, at 7:06 PM, Daniel Child wrote:

    > The only code that gets called is what you saw, however.

    Have you tried stepping through your code line-by-line in the Xcode
    debugger? I agree with Shawn that it's pretty likely an infinite
    recursion problem.

    --
    Mike Blaguszewski / Cocoa Hacker / Ambrosia Software, Inc.
  • Hi Mike,

    I was stepping through until it hits the while loop. A breakpoint
    after that shows that  the error appears to occur at [pool release].
    After canceling the thread stack message, there is a #0 thread that
    reads: NSDecrementExtraRefCountWasZero., followed by 1 [NSObject
    release] and a gazillion [DataParser dealloc]s.

    int main(int argc, char *argv[])
    {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    DataParser *dp = [DataParser parserWithRecordDelim: @"\r"];
    NSString *path, *fullPath, *fileName;
    NSFileManager *NSFm;
    NSMutableArray *data;

    fileName = @"cleaner data.txt";
    NSFm = [NSFileManager defaultManager];
    path = @"<< path name here >>";
    fullPath = [path stringByAppendingPathComponent: fileName];

    data = [dp parseFileAtPath: fullPath];
    [pool release];

    return 0;
    }

    On Aug 31, 2007, at 7:16 PM, Mike Blaguszewski wrote:

    > On Aug 31, 2007, at 7:06 PM, Daniel Child wrote:
    >
    >> The only code that gets called is what you saw, however.
    >
    > Have you tried stepping through your code line-by-line in the Xcode
    > debugger? I agree with Shawn that it's pretty likely an infinite
    > recursion problem.
    >
    > --
    > Mike Blaguszewski / Cocoa Hacker / Ambrosia Software, Inc.
    >
    >
    >
  • So the code you want to show us is -[DataParser dealloc]. Evidently
    it's calling itself.

    Did you close it out with [self dealloc] instead of [super dealloc]?

    — F

    On Aug 31, 2007, at 9:28 PM, Daniel Child wrote:

    > I was stepping through until it hits the while loop. A breakpoint
    > after that shows that  the error appears to occur at [pool release].
    > After canceling the thread stack message, there is a #0 thread that
    > reads: NSDecrementExtraRefCountWasZero., followed by 1 [NSObject
    > release] and a gazillion [DataParser dealloc]s.
  • On 8/31/07, Daniel Child <wchild...> wrote:

    > The only code that gets called is what you saw

    ...except for -[DataParser init], -[DataParser dealloc], etc. :)

    -Shawn
  • No, it was [super dealloc]. Here is the code. Maybe I shouldn't check
    for (self) ?Sorry if this is an obvious mistake. I'm still trying to
    get the basic memory management idioms down.

    - (void) dealloc
    {
      [self setFieldDelim: nil];
      [self setRecordDelim: nil];
      if (self) [self release];
    [super dealloc];
    }

    On Aug 31, 2007, at 10:49 PM, Fritz Anderson wrote:

    > So the code you want to show us is -[DataParser dealloc]. Evidently
    > it's calling itself.
    >
    > Did you close it out with [self dealloc] instead of [super dealloc]?
    >
    > — F
    >
    > On Aug 31, 2007, at 9:28 PM, Daniel Child wrote:
    >
    >> I was stepping through until it hits the while loop. A breakpoint
    >> after that shows that  the error appears to occur at [pool
    >> release]. After canceling the thread stack message, there is a #0
    >> thread that reads: NSDecrementExtraRefCountWasZero., followed by 1
    >> [NSObject release] and a gazillion [DataParser dealloc]s.
    >
  • I think the init method is pretty standard. I'm going to try to
    remove (if (self) [self release]; and see if that helps, though it
    seems to me you would want to release the memory for the instance you
    have created.

    - (id) init;
    {
    self = [super init];
    return self;
    }

    - (void) dealloc
    {
      [self setFieldDelim: nil];
      [self setRecordDelim: nil];
      if (self) [self release];
    [super dealloc];
    }

    On Sep 1, 2007, at 12:11 AM, Shawn Erickson wrote:

    > On 8/31/07, Daniel Child <wchild...> wrote:
    >
    >> The only code that gets called is what you saw
    >
    > ...except for -[DataParser init], -[DataParser dealloc], etc. :)
    >
    > -Shawn
  • The culprit was the dealloc method call if (self) [release self]
    prior to calling [super dealloc].

    I don't understand why that would be a problem. Is the reference to
    super lost if yo release self?

    On Sep 1, 2007, at 12:11 AM, Shawn Erickson wrote:

    > On 8/31/07, Daniel Child <wchild...> wrote:
    >
    >> The only code that gets called is what you saw
    >
    > ...except for -[DataParser init], -[DataParser dealloc], etc. :)
    >
    > -Shawn
  • And there it is. Calling [self release] in dealloc will result in an
    additional call to dealloc. Infinite loop.

    Anyway
    if (self)
      [self release];
    doesn't make sense. You don't get to dealloc unless the last release
    on self has already been encountered.

    Also, unless you set self to nil in the method, if (self)... will
    always evaluate to true.

    — F

    On Sep 1, 2007, at 10:10 AM, Daniel Child wrote:

    > - (void) dealloc
    > {
    > [self setFieldDelim: nil];
    > [self setRecordDelim: nil];
    > if (self) [self release];
    > [super dealloc];
    > }
  • Why would you release yourself?  The dealloc method is called when you are
    being released by someone else.  Just bag the "[release self]" and you
    should be fine.

    > From: Daniel Child <wchild...>
    > Date: Sat, 01 Sep 2007 11:18:02 -0400
    > To: Shawn Erickson <shawnce...>
    > Cc: <cocoa-dev...>
    > Subject: Re: file scan results in EX_BAD_ACCESS
    >
    > The culprit was the dealloc method call if (self) [release self]
    > prior to calling [super dealloc].
    >
    > I don't understand why that would be a problem. Is the reference to
    > super lost if yo release self?
    >
    > On Sep 1, 2007, at 12:11 AM, Shawn Erickson wrote:
    >
    >> On 8/31/07, Daniel Child <wchild...> wrote:
    >>
    >>> The only code that gets called is what you saw
    >>
    >> ...except for -[DataParser init], -[DataParser dealloc], etc. :)
    >>
    >> -Shawn

  • I had forgotten that release calls dealloc. (Just learning
    still....)  Thanks for the explanation.

    On Sep 1, 2007, at 11:19 AM, Fritz Anderson wrote:

    > And there it is. Calling [self release] in dealloc will result in
    > an additional call to dealloc. Infinite loop.
    >
    > Anyway
    > if (self)
    > [self release];
    > doesn't make sense. You don't get to dealloc unless the last
    > release on self has already been encountered.
    >
    > Also, unless you set self to nil in the method, if (self)... will
    > always evaluate to true.
    >
    > — F
    >
    >
    > On Sep 1, 2007, at 10:10 AM, Daniel Child wrote:
    >
    >> - (void) dealloc
    >> {
    >> [self setFieldDelim: nil];
    >> [self setRecordDelim: nil];
    >> if (self) [self release];
    >> [super dealloc];
    >> }
    >
  • On Sep 1, 2007, at 8:10 AM, Daniel Child wrote:

    > I think the init method is pretty standard.

    Nope it isn't. :)

    > - (id) init;
    > {
    > self = [super init];
    > return self;
    > }
    >
    > - (void) dealloc
    > {
    > [self setFieldDelim: nil];
    > [self setRecordDelim: nil];
    > if (self) [self release];
    > [super dealloc];
    > }

    The "if (self) [self release];" is your problem. It points out that
    you may have a fundamental misunderstanding of memory management /
    object life-cycle in Cocoa.

    Read the following the help clear that up...

    <http://developer.apple.com/documentation/Cocoa/Conceptual/
    CocoaFundamentals/CocoaObjects/chapter_3_section_5.html
    >
    <http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/
    index.html
    >

    -Shawn
  • On Sep 1, 2007, at 8:08 AM, Daniel Child wrote:

    > Maybe I shouldn't check for (self)?

    Inside of an instance method self will always point to your object
    instance unless you explicitly set it to something else.

    The "self" local variable (lvar) is passed into the method as a
    hidden parameter (similar to how C++ passes "this"). Also since it is
    an lvar it wont be changed by calls out to functions, etc. unless you
    pass a pointer/reference to them when you call those functions, etc.

    In other words your "if (self)" check doesn't do anything useful (you
    never set self to anything else in that method).

    -Shawn
previous month august 2007 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