On 17.03.2012 21:24, Fred Kiefer wrote:
On 17.03.2012 17:39, Ivan Vučica wrote:
Now that the code in SlaveOPML for creating new outlines from scratch
works
(including saving), I've spent some time trying to figure out why the
program crashes at opening the app. I'm stuck near the beginning; all I
could figure out is the stack trace.

Crash occurs immediately after choosing the file to open, either via the
"Open Recent" menu or via the Open panel.

Program received signal SIGSEGV, Segmentation fault.
0x00ff4a8c in free () from /lib/tls/i686/cmov/libc.so.6
(gdb) bt
#0 0x00ff4a8c in free () from /lib/tls/i686/cmov/libc.so.6
#1 0x0167fbfc in xmlFreeNodeList () from /usr/lib/libxml2.so.2
#2 0x0167fc35 in xmlFreeNodeList () from /usr/lib/libxml2.so.2
#3 0x0168055f in xmlFreeNode () from /usr/lib/libxml2.so.2
#4 0x00cad2bd in -[NSXMLNode dealloc] (self=0x87f72bc, _cmd=0xef2d18) at
NSXMLNode.m:1038
#5 0x00ca5c45 in -[NSXMLElement dealloc] (self=0x87f72bc, _cmd=0xece3b8)
at NSXMLElement.m:49
#6 0x00b83045 in -[NSObject release] (self=0x87f72bc, _cmd=0xeaa150) at
NSObject.m:2049
#7 0x00a4b8c1 in -[NSAutoreleasePool emptyPool] (self=0x819beac,
_cmd=0xeaa0f8) at NSAutoreleasePool.m:656
#8 0x00a4b451 in -[NSAutoreleasePool dealloc] (self=0x819beac,
_cmd=0xeaa160) at NSAutoreleasePool.m:538
#9 0x00a4b3d0 in -[NSAutoreleasePool release] (self=0x819beac,
_cmd=0x7f4c98) at NSAutoreleasePool.m:531
#10 0x0030858e in -[NSApplication run] (self=0x82ec224, _cmd=0x7ee948) at
NSApplication.m:1580
#11 0x002ccd21 in NSApplicationMain (argc=1, argv=0xbffff2b4) at
Functions.m:91
#12 0x0804efaa in main (argc=1, argv=0xbffff2b4) at OPML/main.m:13

Crash seems to happen somewhere in NSXMLElement/NSXMLNode, in a call to
libxml2.

This happens after my -(id)initWithOPMLData:(NSData*)data
error:(NSError**)error has finished already. Although it works when I
create a blank outline, it fails miserably even if I add return [self
initWithBlankOutline]; as the first line of initWithOPMLData:error:.

I'm really unsure how to proceed with debugging. Turning on zombies
didn't
help since the crash occurs in libxml2. I've tried removing some
autoreleases, but to no avail.

NSXMLDocument subclass is not released upon loading (that wouldn't make
sense) and the app works under Cocoa. In fact, I don't really see what
I'm
autoreleasing.

Does anyone have some tips on what I can do?

Alternatively, if anyone is willing to directly look at the problem, to
make testing easier I've also added "example.opml" to the repository
which
is, as always, available at:
http://bitbucket.org/ivucica/opml


I think that you did run into a conceptual problem of our current
libxml2 handling. After installing the debug infor for libxml2 it is
easy to see that your code fails within the line tree.c:3651 that is

DICT_FREE(cur->name)

Here the name of the node is free, but this includes a test, whether the
name was allocated directly or comes from the dictionary of the
document, a way libxml2 uses to save space.
Now that we have unlinked the node from the document and even freed the
document, the relationship to the dictionary is no longer there and the
node thinks it can free the name directly, but of course this wont work.
Now we are back to square zero. All the stuff that we have implemented
works rather nicely, but we did not consider this case. Here we may
either copy all strings with xmlStrdup and thereby blow up the memory
used by XML data or keep the document, and its dictionary around all the
time. Maybe even leaking it. All of this seems just stupid and I am
considering this design a bug in libxml2. How is this supposed to work
when a node gets transferred to a different document?

Sorry, I am a bit clueless here. Anybody out there with a solution?

I rewrote the ownership transfer for nodes once more. I am now using the function xmlDOMWrapAdoptNode() and create a private document for standalone nodes. (Which actually isn't as private as it needs to be) This means when we detach a node from its parent (and this node has a document assigned to it) we create a new private document and transfer the node to this. When the node gets attached to a new parent, we do the opposite and transfer it to the new document, freeing up our private document. When deallocating a node, we know that it can no longer be attached to a parent node, this mean, we again have to free the private document.

This is a lot more overhead then the solution we used before, but should be a lot more correct. At least your example code runs again and all our test cases work. (Which isn't too much of an argument.)


_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/gnustep-dev

Reply via email to