0

I have an NSOutlineTableView that is displaying hierarchical HTML data, loaded from an HTML parser (each HTML tag is an object with attributes and an array of it's children). For some reason, this code crashes AFTER it has run through all the objects. That is to say, I see NSLog() results for all objects in the HTML, but after that the code crashes:

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item{

    if (item==nil) {
        item=rootNode;
    }
    NSLog(@"looking for child %d of element %@",index, item);
    return [[item children] objectAtIndex:index];

}


- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item{

    if (item==nil) {
        item=rootNode;
    }
    NSLog(@"Element %@ has %i children", item, [[item children] count]);
    return [[item children ]count];

}


- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item{

    NSLog(@"is item %@ with %@ children expandable?",item,[item children]);
    return [[item children] count]>0;

}


- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item{

    if (![item isKindOfClass:[HTMLNode class]]) {   //////CRASH ON THIS LINE (or at least in this function)
        return @"";
    }

    NSLog(@"Object value for: %@",item);

    return [NSString stringWithFormat:@"%@",[item description]];

}

Here is an example run: HTML content: @"<ul></ul><span class='spantext1'></span><span class='spantext2'></span>";

Output:

Element <HTMLNode: 0x7fb9234462a0> body has 3 children

looking for child 0 of element <HTMLNode: 0x7fb9234462a0> body

is item <HTMLNode: 0x7fb923437d40> ul with (
) children expandable?

Object value for: <HTMLNode: 0x7fb923437d40> ul

looking for child 1 of element <HTMLNode: 0x7fb9234462a0> body

is item <HTMLNode: 0x7fb9249255c0> span with (
) children expandable?

Object value for: <HTMLNode: 0x7fb9249255c0> span

looking for child 2 of element <HTMLNode: 0x7fb9234462a0> body

is item <HTMLNode: 0x7fb92491e1d0> span with (
) children expandable?

Object value for: <HTMLNode: 0x7fb92491e1d0> span
(lldb) (crash with EXC_BAD_ACCESS)

Here is the top of the call stack:

objc_msgSend() selector name: isKindOfClass:
objc[23702]: garbage collection is OFF

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libobjc.A.dylib                 0x00007fff846e7110 objc_msgSend_vtable4 + 16
1   com.303DesignLabs.SiteStats     0x0000000109dd44fd -[HTMLTreeOutlineController outlineView:objectValueForTableColumn:byItem:] + 189 (HTMLTreeOutlineController.m:51)

It almost appears as if it's trying to run objectValueForTableColumn once more, after all the data has been run thru. Like I said, the crash occurs after the entire object hierarchy has been run thru (as evidenced by terminal output). At any rate, before the crash the tableView appears on the screen for a split second, with all three elements in their respective rows.

Chris
  • 1,037
  • 15
  • 26

1 Answers1

1

"EXC_BAD_ACCESS" usually means you're trying access a nil object or pointer.

And from what I can see in your code up there, it looks like you're always assuming "[item children]" is not nil.

What happens if "[item children]" has no children? is the result NULL? Should you be calling objectAtIndex or count on a NULL object? My guess is NO.

You should probably return something sensible for each function if there are no children for any given item.

Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
  • [item children] is always not NULL, if the item has no children, the array is simply empty. At any rate, the crash isn't happening on a call to [item children], but rather to any reference to item after the last element is displayed (in this case, [item isKindOfClass:]. The last call on the stack is objc_msgSend_vtable4, if that means anything to anyone... – Chris Apr 20 '12 at 00:06
  • thanks for adding the itty bitty backtrace. Is item valid or is it "`nil`" in the line before it crashes? Also, are you using ARC and how is the item data referred to in your code (i.e. any chance the data is going stale or being released right before the crash)? – Michael Dautermann Apr 20 '12 at 00:14
  • No problem. Let's see.. ARC is off. The item doesn't evaluate to nil or NULL, however the address that xCode gives me for the bad object is never seen before in parsing. The objects are all created in the HTML parser that I got off the internet, which is a Cocoa wrapper around libxml/HTMLparser, so I haven't touched the memory management there. Is there a chance it's just a bug in the parser? – Chris Apr 20 '12 at 00:24
  • Answered my own question, kind of. Turns out it seems to be a bug in the HTML parser code, so I went shopping for other parsers and found one that works perfectly. Well, thanks a lot for the help! Haha just wish I would have thought of that sooner, I seem to need to stop trusting libraries from the internet lol. ^.^ – Chris Apr 20 '12 at 00:42