free () для члена структуры вызывает Hardfault только в Debug - PullRequest
3 голосов
/ 13 июня 2019

Я работаю на STM32F7.Hardfault срабатывает, когда я нажимаю free() в следующем (упрощенном) коде:

typedef struct
{
    uint8_t size;
    uint8_t* data;
}my_struct;

void foo()
{
     my_struct msg;
     msg.size = 5;
     msg.data = malloc(msg.size);
     if(msg.data != NULL)
     {
         free(msg.data); // Hardfault
     }
}

Шаг за шагом, используя GDB в free() Я нашел инструкцию по сборке, которая вызвала Hardfault:

ldrd    r1, r3, [r5, #8]

Значение r5 равно 0x5F0FE9D0

CFSR равно 0x8200, и оба регистра MMFAR и BFAR содержат 0x5F0FE9D8,

Глядя на LDRDR проблемы в сети, я попытался добавить __attribute__((__packed__)) к my_struct определению.Предполагается, что вместо принудительного доступа к памяти через указатели / структуры компилятор генерирует 2x LDR .

Благодаря этому у меня больше не возникает Hardfault во время выполнения.ОК ...

Из любопытства я хотел проверить адреса через GDB после этой модификации, и удивляюсь!Ничего не меняется (я имею в виду адреса), и я заканчиваю тем, что снова нажимаю на инструкцию LDRD , несмотря на packed, и генерирую мой Hardfault (но только при выполнении отладки GDB).

Я запустил новый прогон после удаления атрибута и сравнил значение регистров MMFAR и BFAR, а когда я не в GDB, я получил 0x41AFFE60

  • Почему я не вижу2x LDR в отладчике?
  • В более общем смысле, почему у меня нет одинакового поведения с GDB и без него?
  • Является ли уловка packed хорошим решением для моей проблемы?

PS Я использую FreeRTOS и определил configCHECK_FOR_STACK_OVERFLOW для 2 и configASSERT, ничего не срабатывает.

Ответы [ 2 ]

5 голосов
/ 13 июня 2019

И 0x5F0FE9D8, и 0x41AFFE60 помечены как зарезервированные на карте памяти STM32F7 (глава 2 Справочного руководства). Это означает, что повреждена куча .

Почему я не вижу 2xLDR в отладчике?

Поскольку free() находится в предварительно скомпилированной статической библиотеке, она не перекомпилируется.

В более общем смысле, почему у меня нет одинакового поведения с GDB и без него?

Если куча содержит случайный мусор, либо потому, что он не инициализирован должным образом, либо перезаписан каким-то несвязанным фрагментом кода, вы можете получить другой мусор, когда подключаете или отключаете что-то от платы. Или когда меняется какой-либо фактор окружающей среды.

Является ли уловка packed хорошим решением для моей проблемы?

Нет, просто удаётся спрятать проблему по счастливой случайности. С поврежденной кучей все ставки сняты.

0 голосов
/ 13 июня 2019

Вы начинаете отладку не с того конца. Вы проверяли значение, возвращаемое malloc? Возможно нет.

Если адрес неверен, это обычно означает, что ваш скрипт компоновщика неверен.

Покажите нам все. Результат malloc, фактический код и скрипт компоновщика.

...