我在ARM linux平台上遇到了一个非常奇怪的崩溃问题。 问题是它很少再生(每天一次)而另一个问题是它崩溃的地方实际上不能。
让我们从C ++代码开始。线程函数执行此操作:
event_obj events[EVENTS_MAX]; // EVENTS_MAX = 32
int num = 0;
m_engine->getEvents(events, &num);
engine
是指向基本抽象类的指针,该抽象类目前只有一个实现。 getEvents是纯虚方法。
getEvents
经过一些更改后,除此之外什么都没做。
int engine::getEvents(event_obj*, int* num)
{
if (num != nullptr)
{
*num = 0; // SEGMENTATION FAULT
}
return 1; // ok
}
尝试在num中存储0时发生SEGFAULT。首先我认为它是堆栈损坏,但在我检查生成的汇编代码后,似乎没有任何东西存储在堆栈中。这种方法甚至不会产生堆栈保护(启用-fstack-protector-strong),两个参数都存储在寄存器r1和r2中。 让我们看一下函数调用的代码:
event_obj events[EVENTS_MAX];
int num = 0;
236f8: 2300 movs r3, #0
236fa: ac06 add r4, sp, #24
236fc: 9306 str r3, [sp, #24]
m_engine->getEvents(events, &num);
236fe: 6803 ldr r3, [r0, #0]
23700: 691b ldr r3, [r3, #16]
23702: 4622 mov r2, r4
23704: a90c add r1, sp, #48 ; 0x30
23706: 4798 blx r3
以及函数本身的代码:
int engine::getEvents(event_obj*, int* num)
{
if (num != nullptr)
251f8: 4613 mov r3, r2
251fa: b10a cbz r2, 25200 <_Z18engine_thread_funcPv+0x9e0>
{
*num = 0;
251fc: 2200 movs r2, #0
251fe: 601a str r2, [r3, #0]
}
return 1; // ok
}
25200: 2001 movs r0, #1
25202: 4770 bx lr
return 1; // ok
}
从生成的代码中可以看出,指针放在int r1
和r2
寄存器中。
23702: 4622 mov r2, r4
23704: a90c add r1, sp, #48 ; 0x30
即使堆栈已损坏,它也可能损坏num
变量的值,但它如何破坏寄存器中的指针?同样从崩溃日志中我可以看到LR
地址错误。
CRASH信号11分段故障地址0xf0000000 PC 0x251fe LR 0x6c3c533c
我在这里唯一看不到的是跳转地址(blx r3),因为被调用的方法是虚拟的。 我有一个非常不可能的假设,它不是跳到虚拟方法体的第一行,而是在它之前跳到了几行并且损坏了寄存器,但我不知道怎么可能。即使在更改代码之后,它也始终在同一行崩溃。这很奇怪。
有人可以提出尝试吗?有什么想法吗?
提前致谢。
答案 0 :(得分:2)
发生故障是因为引擎不再有效。包含引擎的方法可能已被解除分配 - 即,您的线程内存已消失。因此,engine-getevents在内存中甚至无效。代码中的其他地方发生了某些事情,线程应该已经停止运行 - 并退出。他们没有。这很像是对正在退出的应用程序的回调。