SEGFAULT正在写入堆栈变量



我在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
}

SEGFAULT发生在尝试将0存储在num.起初我认为这是堆栈损坏,但在我检查生成的汇编代码后,堆栈中似乎没有存储任何内容。此方法甚至没有生成堆栈保护(启用了-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
}

从生成的代码中可以看到,指针被放在r1r2寄存器中。

23702:       4622            mov     r2, r4
23704:       a90c            add     r1, sp, #48     ; 0x30

即使堆栈已损坏,它也可能损坏num变量的值,但它怎么能损坏寄存器中的指针呢?此外,从崩溃日志中,我可以看到LR地址是错误的。

CRASH信号11分段故障地址0xf0000000 PC 0x251fe LR0x6c3c533c

从这里我唯一看不到的是跳转的地址(blx r3),因为被调用的方法是虚拟的。我有一个非常不可能的假设,即它没有跳到虚拟方法体的第一行,而是跳到了之前的几行,并损坏了寄存器,但我不明白这是怎么可能的。而且它总是在同一行崩溃,即使在更改代码之后也是如此。这很奇怪。

有人能提出一些尝试的建议吗?有什么想法吗?

提前谢谢。

由于引擎不再有效而发生故障。包含引擎的方法可能已被释放,即线程内存已不存在。因此,引擎getevents在内存中甚至是无效的。代码中的其他地方发生了一些事情,线程应该停止运行并退出。他们没有。这很像是对正在退出的应用程序的回调。

相关内容

  • 没有找到相关文章

最新更新