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
}

как видно из сгенерированного кода, указатели ставятся в r1 а также r2 регистры.

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

Даже если стек поврежден, он может испортить значение для num переменная, но как это может повредить указатель в регистре? Также из краш-журнала я вижу, что LR адрес неверный.

Сигнал CRASH 11 Адрес ошибки сегментации 0xf0000000 ПК 0x251fe LR
0x6c3c533c

Единственное, что я не вижу здесь, это адрес перехода (blx r3), потому что вызываемый метод является виртуальным.
У меня есть одно очень маловероятное предположение, что вместо перехода к первой строке тела виртуального метода он переместился на несколько строк до этого и испортил регистры, но я не понимаю, как это возможно. Также он всегда вылетает на одной строке, даже после изменения кода. Это очень странно.

Может кто-нибудь предложить что-нибудь попробовать? Есть идеи?

Заранее спасибо.

0

Решение

Ошибка происходит, потому что двигатель больше не действителен. Метод, содержащий движок, вероятно, был освобожден — т. Е. Память вашего потока пропала. Таким образом, двигатель-getevents даже не действует в памяти. Что-то произошло где-то еще в вашем коде, и потоки должны были перестать работать — и завершиться. Они не имеют. Это очень похоже на обратный вызов в приложение, которое выходит.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]