exc_breakpoint崩溃的原因

Cause of EXC_BREAKPOINT crash

本文关键字:崩溃 breakpoint exc      更新时间:2023-10-16

我在逻辑X中运行的C 录音组件中的某些用户计算机上发生了崩溃。不幸的是,我无法在本地重复,并且在尝试解决如何解决的过程中可能发生了一些问题。

这是崩溃转储的相关信息:

Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5
Terminating Process: exc handler [0]

问题是:

  • 在我看的情况下可能导致exc_breakpoint的原因。来自Apple的信息是完整而准确的:"类似于异常出口,此例外旨在使附件的调试器有机会在执行的特定点中断过程。您可以从您自己身上触发此例外使用__builtin_trap((函数的代码。如果没有附加调试器,则终止该过程并生成崩溃报告。"
  • 为什么会发生在共享对象 200上(请参阅拆卸(
  • 是rbx当崩溃发生的那一刻。

崩溃发生在这里:

juce::ValueTree::SharedObject::SharedObject(juce::ValueTree::SharedObject const&) + 200

C 如下:

SharedObject (const SharedObject& other)
    : ReferenceCountedObject(),
      type (other.type), properties (other.properties), parent (nullptr)
{
    for (int i = 0; i < other.children.size(); ++i)
    {
        SharedObject* const child = new SharedObject (*other.children.getObjectPointerUnchecked(i));
        child->parent = this;
        children.add (child);
    }
}

拆卸:

->  0x127167950 <+0>:   pushq  %rbp
    0x127167951 <+1>:   movq   %rsp, %rbp
    0x127167954 <+4>:   pushq  %r15
    0x127167956 <+6>:   pushq  %r14
    0x127167958 <+8>:   pushq  %r13
    0x12716795a <+10>:  pushq  %r12
    0x12716795c <+12>:  pushq  %rbx
    0x12716795d <+13>:  subq   $0x18, %rsp
    0x127167961 <+17>:  movq   %rsi, %r12
    0x127167964 <+20>:  movq   %rdi, %rbx
    0x127167967 <+23>:  leaq   0x589692(%rip), %rax      ; vtable for juce::ReferenceCountedObject + 16
    0x12716796e <+30>:  movq   %rax, (%rbx)
    0x127167971 <+33>:  movl   $0x0, 0x8(%rbx)
    0x127167978 <+40>:  leaq   0x599fe9(%rip), %rax      ; vtable for juce::ValueTree::SharedObject + 16
    0x12716797f <+47>:  movq   %rax, (%rbx)
    0x127167982 <+50>:  leaq   0x10(%rbx), %rdi
    0x127167986 <+54>:  movq   %rdi, -0x30(%rbp)
    0x12716798a <+58>:  leaq   0x10(%r12), %rsi
    0x12716798f <+63>:  callq  0x12711cf70               ; juce::Identifier::Identifier(juce::Identifier const&)
    0x127167994 <+68>:  leaq   0x18(%rbx), %rdi
    0x127167998 <+72>:  movq   %rdi, -0x38(%rbp)
    0x12716799c <+76>:  leaq   0x18(%r12), %rsi
    0x1271679a1 <+81>:  callq  0x12711c7b0               ; juce::NamedValueSet::NamedValueSet(juce::NamedValueSet const&)
    0x1271679a6 <+86>:  movq   $0x0, 0x30(%rbx)
    0x1271679ae <+94>:  movl   $0x0, 0x38(%rbx)
    0x1271679b5 <+101>: movl   $0x0, 0x40(%rbx)
    0x1271679bc <+108>: movq   $0x0, 0x48(%rbx)
    0x1271679c4 <+116>: movl   $0x0, 0x50(%rbx)
    0x1271679cb <+123>: movl   $0x0, 0x58(%rbx)
    0x1271679d2 <+130>: movq   $0x0, 0x60(%rbx)
    0x1271679da <+138>: cmpl   $0x0, 0x40(%r12)
    0x1271679e0 <+144>: jle    0x127167aa2               ; <+338>
    0x1271679e6 <+150>: xorl   %r14d, %r14d
    0x1271679e9 <+153>: nopl   (%rax)
    0x1271679f0 <+160>: movl   $0x68, %edi
    0x1271679f5 <+165>: callq  0x12728c232               ; symbol stub for: operator new(unsigned long)
    0x1271679fa <+170>: movq   %rax, %r13
    0x1271679fd <+173>: movq   0x30(%r12), %rax
    0x127167a02 <+178>: movq   (%rax,%r14,8), %rsi
    0x127167a06 <+182>: movq   %r13, %rdi
    0x127167a09 <+185>: callq  0x127167950               ; <+0>
    0x127167a0e <+190>: movq   %rbx, 0x60(%r13)        // MY NOTES: child->parent = this
    0x127167a12 <+194>: movl   0x38(%rbx), %ecx
    0x127167a15 <+197>: movl   0x40(%rbx), %eax
    0x127167a18 <+200>: cmpl   %eax, %ecx

更新1:看来RIP暗示我们处于"添加"调用的中间,这是此功能,分别为:

/** Appends a new object to the end of the array.
    This will increase the new object's reference count.
    @param newObject       the new object to add to the array
    @see set, insert, addIfNotAlreadyThere, addSorted, addArray
*/
ObjectClass* add (ObjectClass* const newObject) noexcept
{
    data.ensureAllocatedSize (numUsed + 1);
    jassert (data.elements != nullptr);
    data.elements [numUsed++] = newObject;
    if (newObject != nullptr)
        newObject->incReferenceCount();
    return newObject;
}

更新2:在相关寄存器的崩溃寄存器值时:

this == rbx: 0x00007fe5bc37c950
&other == r12: 0x00007fe5bc348cc0
rax = 0
rcx = 0

我怀疑问题在于,应该在堆栈上无意中分配了一个应该放置在堆上的共享的,朗格计数的对象。如果堆栈随后放松并被覆盖,并且对ref计数对象的引用仍然存在,那么随机的事情将在访问该引用的情况下发生不可预测的时间发生。(在地址空间的接近和其他方面的距离也使我怀疑两者都在堆上。(

此代码中可能有一些问题:

  • 就像SM所提到的,其他.Children.GetObjectPoTewercecked(i(可以返回nullptr
  • ObjectClass* add (ObjectClass* const newObject) noexcept中,您在调用 incReferenceCount之前检查了newObject是否没有null(这意味着在此方法调用中可能发生null(,但是在data.elements [numUsed++] = newObject;期间添加此对象之前,您不会取消检查,因此您可能有一个nullptr在这里,如果您在没有检查的地方将此数组拨打在其他地方,则可能会崩溃。
  • 我们真的不知道数据的类型(我假设一个数组(,但是由于指针分配,可能会发生副本操作(如果指针转换为对象,如果数据。一个指针或有一些操作员过载(,这里可能发生崩溃(但不可能(
  • 儿童与父母之间有一个循环裁判,因此在物体破坏过程中可能存在问题