Jump to content

    

Отладка и выход за пределы массивов

Подскажите, есть ли способ под FreeRTOS понять есть ли выходы за предел массива. Хуки на недостаток хипа и стека работают нормально и очень помогают, когда нужно зажать стек задачи до минимума. Но как отладить выход за пределы массивов? Такая необходимость появилась, так как иногда устройства перезагружаются сами по себе(в обработчиках исключений стоит функция сброса, так как устройства должны максимально быть доступны). Есть подозрение на выход за пределы. Так как проект достаточно крупный около 300кб кода с оптимизацией, пересмотреть, а главное заметить ошибку очень сложно.

Кто, что может порекомендовать?

Share this post


Link to post
Share on other sites
Подскажите, есть ли способ под FreeRTOS понять есть ли выходы за предел массива. Хуки на недостаток хипа и стека работают нормально и очень помогают, когда нужно зажать стек задачи до минимума. Но как отладить выход за пределы массивов?

А какое имеет отношение FreeRTOS или какая другая ОС к вашим массивам?

Читайте описание на используемый процессор.

Для Cortex-M - читать описание MPU.

Share this post


Link to post
Share on other sites
...Кто, что может порекомендовать?

 

Наберите людей на испытательный срок. С условием = найдут проблемы, бонусы.

А для программиста = обратная задача. Найдётся баг - из его зарплаты минусы.

 

Думаю проблемЫ найдутся быстро, тоннами и качественно.

 

Не технический путь, но профит будет 100%

 

удачи вам

(круглый)

ЗЫ

Если технически - наверное пытаться эмулировать работу логики. + изоляция памяти, с анализом на перезатирку. Но профит будет меньше чем в первом случае...

 

Share this post


Link to post
Share on other sites

Для начала стоит перенести код в настольный ПК и погонять на модели под отладчиком, напихав туда проверок при каждом обращении к массивам. Ну и статические анализаторы типа CPP-Check или PVS-Studio помогают найти некоторые ошибки.

Share this post


Link to post
Share on other sites

1. Проработайте код аналитически, тк выход за границы массива "чем-то" - грубая ошибка, скорее всего программера а не компилятора или OS.

2. Используйте "на полную" возможности отладчика, например IAR. Настройте BP на стоп по изменению памяти (write).

Ставите такй BP на ячейку (адрес) за пределами массива и .... ждете :)

3. Ну, можно "наложить" в памяти 2 массива. (&WorkArry[0] == &DbgArry[0])

Один - большой, отладочный, который перекрывает по размеру "проблемный".

Заполняете отладочный массив паттерном, напр. 0x55.

Второй массив - Ваш "проблемный". После сбоя смотрим паттерны в отладочном массиве выше последней ячейки "проблемного".

 

ps/ п.3.

При остановке в этой BP, через StackCall будет видно, кто там "порылся".

Share this post


Link to post
Share on other sites
Наберите людей на испытательный срок. С условием = найдут проблемы, бонусы.

А для программиста = обратная задача. Найдётся баг - из его зарплаты минусы.

Думаю проблемЫ найдутся быстро, тоннами и качественно.

Вот именно! ... когда люди на испытательном сроке познакомятся с программистом делающим баги, я думаю они быстро найдут формулу взаимовыгодного сотрудничества: "утром баги, вечером бонусы" или "вечером баги, утром бонусы".

И все будут довольны: люди - бонусами, программист откатами от бонусов людей, а хозяин тоннами находимых и находимых багов... :biggrin: :biggrin: :biggrin: :biggrin:

 

Ставите такй BP на ячейку (адрес) за пределами массива и .... ждете :)

На какую именно ячейку "за пределами"? Если к примеру массив == 10 байт, а размер памяти МК == 1<<32, то на какую из

(1<<32)-10 ячеек ставить? На все? Боюсь что жизни не хватит. :laughing:

 

При остановке в этой BP, через StackCall будет видно, кто там "порылся".

char m[10];

int i = char[20]; //однако проблема!

И как же именно будет видно "через StackCall" или через некие "паттерны" кто порылся в вышеприведённом фрагменте кода??? :wacko:

Share this post


Link to post
Share on other sites
. . .

(1) На какую именно ячейку "за пределами"? Если к примеру массив == 10 байт, а размер памяти МК == 1<<32, то на какую из

. . .

(2) . . И как же именно будет видно "через StackCall" или через некие "паттерны" кто порылся в вышеприведённом фрагменте кода???

1 - понятно, что если вылет идет с "фонарным" индексом то это не вариант.

Если же это примитивный "зашкал" по sprintf - то вполне. (кто не пользуется snprintf)

 

2. Это не мое "изобретение", метода исползуется для контроля использования стека в scmRTOS.

Для чтения за пределами массива - никак. Разве что знать, что считывается определенный адрес и BP поставить на него. Смотреть стек вызовов.

Для чтения более целесообразно смотреть что попадает в [] а не вылавливать последствия. С указателем сложнее.

//    Target-specific configuration macros
//
#ifdef scmRTOS_USER_DEFINED_STACK_PATTERN
#define scmRTOS_STACK_PATTERN scmRTOS_USER_DEFINED_STACK_PATTERN
#else
#define scmRTOS_STACK_PATTERN 0x55aaU
#endif

Share this post


Link to post
Share on other sites
2. Это не мое "изобретение", метода исползуется для контроля использования стека в scmRTOS.

И что? "Метод" не даёт никакой гарантии. Подумайте, что будет при вызове функции:

void func() {
int m[100];
...
}

если вызов происходит вблизи границы стека. Да и не про стек вопрос автора.

 

Для чтения за пределами массива - никак.

Как. Если знать какой CPU у автора. Для Cortex-M я уже написал выше как. Для CPU с MMU - ещё лучше. И чтение и произвольная запись. Именно - произвольная, а не только в следующий адрес после массива.

Share this post


Link to post
Share on other sites

Спасибо всем за ответы. Их действительно много и они вполне перекрывают вопрос. Думаю лучший способ настроить MPU(cortex m4) + в некоторых местах сделаю массивы на длину +1 элемент и поставлю туда брейкпоинт на запись и чтение. Вариант с перекрытием массивов очень сложен, так как кода много и проблемный массив неизвестен. Аналитически код был просмотрен уже неоднократно, был найден один ляп с приведением типов, но это не изменило ситуацию в корне. Так же интересует, в случае фриртоса и выделения памяти в хипе, если будет затерт конец массива выделенной памяти, будет ли вызван ассерт во время фрии, или в конце нет данных маллока для отслеживания окончания массива(используется heap4.c + его модификация под CCM память)? Вариант с испытательным сроком очень оригинален. Всем спасибо :)

Edited by Neo_Matrix

Share this post


Link to post
Share on other sites
Так как проект достаточно крупный около 300кб кода с оптимизацией, пересмотреть, а главное заметить ошибку очень сложно.

Кто, что может порекомендовать?

Анализаторами кода пользовались? PVS-studio писали что адаптировались под Keil/IAR, только у меня руки не дошли проверить.

Share this post


Link to post
Share on other sites
Спасибо всем за ответы. ...

 

Статические анализаторы, как тут уже прозвучало - это бы первое, что попробовал бы.

Из статических и фрии анализаторов - есть кстати сонар. Он вроде как достаточно мощная вещь. Сам юзал, но для большого брата и не сей...

 

Но имхо - проблема не в коде, а в организации...

 

удачи вам

(круглый)

 

Share this post


Link to post
Share on other sites
И что? "Метод" не даёт никакой гарантии. Подумайте, что будет при вызове функции:

void func() {
int m[100];
...
}

если вызов происходит вблизи границы стека. Да и не про стек вопрос автора.

. . .

А какие могут быть гарантии при отладке каким-либо одним методом ?

Смею предположить, что затрется адрес возврата или контекст. Вообще - что угодно.

 

void func() 
{
static int m[100];
...
}

Если характер сбоя изменился или он вообще перестал проявляться - некорректная работа с этим массивом.

Спасибо всем за ответы. Их действительно много и они вполне перекрывают вопрос. Думаю лучший способ настроить MPU(cortex m4) + в некоторых местах

. . .

Если RAM позволяет, попробуйте массив(ы) которые "под подозрением" объявить как static.

Share this post


Link to post
Share on other sites
И что? "Метод" не даёт никакой гарантии. Подумайте, что будет при вызове функции:

Гарантий нет, но в жизни это самый быстрый и действенный способ.

Share this post


Link to post
Share on other sites

Всем спасибо. Ошибка найдена. Функции strncmp при определенных стечениях обстоятельств передавался NULL вместо валидного указателя.

Share this post


Link to post
Share on other sites
Всем спасибо. Ошибка найдена. Функции strncmp при определенных стечениях обстоятельств передавался NULL вместо валидного указателя.

Вообще в нормально построенной программе на Cortex-M все области вне регионов ОЗУ обычно запрещаются для доступа по записи, а все регионы где вообще нет никакой памяти запрещаются для любого типа доступа. Для этого и предназначен MPU. Если-б у Вас программа была построена так, то скорей всего ошибка нашлась бы при первом же её проявлении.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this