Wow. It's tough to figure out where the CPU is in a large project with limited symbols. No source lines (that I could find) in the released binary, so I was looking in the wrong area for a long time. It doesn't help that I haven't touched x86 assembly in decades, or that I don't use
lldb much.
Looking at the source for the tip of the backtrace, I found this gem:
https://github.com/FreeCAD/FreeCAD/blob ... .cpp#L3221
Code: Select all
ViewProviderDocumentObject *DocumentItem::getViewProvider(App::DocumentObject *obj) {
// Note: It is possible that we receive an invalid pointer from
// claimChildren(), e.g. if multiple properties were changed in
// a transaction and slotChangedObject() is triggered by one
// property being reset before the invalid pointer has been
// removed from another. Currently this happens for
// PartDesign::Body when cancelling a new feature in the dialog.
// First the new feature is deleted, then the Tip property is
// reset, but claimChildren() accesses the Model property which
// still contains the pointer to the deleted feature
//
// return obj && obj->getNameInDocument() && pDocument->isIn(obj);
//
// TODO: is the above isIn() check still necessary? Will
// getNameInDocument() check be sufficient?
if(!obj || !obj->getNameInDocument()) return 0;
That check at the end would only catch null
obj pointers. It wouldn't catch the "invalid pointer" described in the comments above.
getNameInDocument does one more sanity check. However, it also only looks for a null pointer -- in a potentially-invalid object.
On x64, MacOS, I see this on one crash:
Code: Select all
(lldb) disassemble
libFreeCADApp.dylib`App::DocumentObject::getNameInDocument:
0x1015e1170 <+0>: pushq %rbp
0x1015e1171 <+1>: movq %rsp, %rbp
0x1015e1174 <+4>: movq 0x300(%rdi), %rax
0x1015e117b <+11>: testq %rax, %rax
0x1015e117e <+14>: je 0x1015e118a ; <+26>
-> 0x1015e1180 <+16>: testb $0x1, (%rax)
0x1015e1183 <+19>: jne 0x1015e118e ; <+30>
0x1015e1185 <+21>: incq %rax
It's past the null-pointer check (<+11>) and tried to read memory at (%rax) which has an inaccessible address in it according to the debugger. No surprise there...
Select registers and the resulting try to access the memory in debugger below:
Code: Select all
(lldb) register read
General Purpose Registers:
rax = 0x40060b0100000000
...
rdi = 0x0000000107df3e00
rsi = 0x0000000107df3e00
rbp = 0x00007ffeefbfaf30
rsp = 0x00007ffeefbfaf30
...
rip = 0x00000001015e1180 libFreeCADApp.dylib`App::DocumentObject::getNameInDocument() const + 16
rflags = 0x0000000000010206
...
(lldb) memory read 0x40060b0100000000
error: memory read failed for 0x40060b0100000000