gpt4 book ai didi

c++ - EXC_BREAKPOINT 崩溃的原因

转载 作者:行者123 更新时间:2023-11-30 03:25:42 37 4
gpt4 key购买 nike

我在 Logic X 中运行的 C++ audiounit 组件中的一些用户计算机上发生了崩溃。不幸的是,我无法在本地重复它,并且在尝试弄清楚它是如何发生的过程中我得到了一些问题。

以下是故障转储中的相关信息:

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() 函数的代码。如果没有附加调试器,进程将终止并生成崩溃报告。”
  • 为什么它会出现在 SharedObject + 200 上(参见反汇编)
  • RBX 是崩溃发生时的“this”指针吗?

崩溃发生在这里:

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:在相关寄存器的crash寄存器值处:

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

最佳答案

这段代码可能存在一些问题:

  • 像 SM 提到的,other.children.getObjectPointerUnchecked(i) 可以返回 nullptr
  • ObjectClass* 中添加 (ObjectClass* const newObject) noexcept,在调用 incReferenceCount 之前检查 newObject 是否不为 null(这意味着此方法中可能出现 null调用),但在 data.elements [numUsed++] = newObject; 期间添加此对象之前不进行 null 检查,因此此处可能有一个 nullptr,并且如果您在其他地方调用此数组而没有检查,你可能遇到了崩溃。
  • 我们真的不知道 data.elements 的类型(我假设是一个数组),但是由于指针赋值可能会发生复制操作(如果指针被转换为对象,如果 data.elements 不是一个指针数组或有一些运算符重载),这里可能会发生崩溃(但不太可能)
  • children和parent之间存在循环引用,所以对象销毁时可能会出现问题

关于c++ - EXC_BREAKPOINT 崩溃的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48849479/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com