реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Аномальное поведение переменной в Си (STM32F4)
flopix
сообщение Jan 25 2013, 21:10
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 105
Регистрация: 21-06-12
Пользователь №: 72 429



Разбираюсь с программным декодером mp3 Helix, на отладке Stm32F4Discovery.
При попытке декодирования потока данных МК постоянно вылетает по HardwareException. Теcтирую в среде Keil через встроенный в макетку отладчик. Начал разбираться и появились некоторые вопросы.

В библиотеке есть структура
Код
typedef struct _FrameHeader {
    MPEGVersion ver;    /* version ID */
    int layer;            /* layer index (1, 2, or 3) */
    int crc;            /* CRC flag: 0 = disabled, 1 = enabled */
    int brIdx;            /* bitrate index (0 - 15) */
    int srIdx;            /* sample rate index (0 - 2) */
    int paddingBit;        /* padding flag: 0 = no padding, 1 = single pad byte */
    int privateBit;        /* unused */
    StereoMode sMode;    /* mono/stereo mode */
    int modeExt;        /* used to decipher joint stereo mode */
    int copyFlag;        /* copyright flag: 0 = no, 1 = yes */
    int origFlag;        /* original flag: 0 = copy, 1 = original */
    int emphasis;        /* deemphasis mode */
    int CRCWord;        /* CRC word (16 bits, 0 if crc not enabled) */

    const SFBandTable *sfBand;
} FrameHeader;

В ней меня сейчас интересует объявление указателя const SFBandTable *sfBand;
где
Код
typedef struct _SFBandTable {
    short l[23];
    short s[14];
} SFBandTable;


Переменная объявлена глобально следующим образом:
Код
FrameHeader fh;


Далее присваивается
Код
fh->sfBand = &sfBandTable[0][0];


массив sfBandTable объявлен как константа
Код
const SFBandTable sfBandTable[3][3] = {
    {
        /* MPEG-1 (44, 48, 32 kHz) */
        {
            { 0,  4,  8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90,110,134,162,196,238,288,342,418,576 },
            { 0,  4,  8, 12, 16, 22, 30, 40, 52, 66, 84,106,136,192 }
        },

......


после выполнения этой строки в отладчике видно что указатель установлен правильно, так как массив корректно заполнился значениями из таблицы SFBandTable.
Прикрепленное изображение


Далее идет самое интересное. В одной из функций объявляется небольшой массив
[PHP]int cbMax[3];[/PHP]
и компилятор почему то решает разместить последний элемент массива cbMax по адресу указателя fh->sfBand
Прикрепленное изображение


И когда выполняется присваивание
Код
cbMax[2] = 0;


Слетает указатель на таблицу sfBandTable
Прикрепленное изображение


Подскажите что копать. До функции где объявлен массив cbMax выполняется куча кода, создается и уничтожается куча переменных, но и именно в этой функции всегда возникает проблема.



Попробовал перед массивом int cbMax[3]; объявить еще один другого размера int test1[5]; для теста и опять именно последний элемент уже нового массива налез на ячейку где сохранен указатель в моей структуре на таблицу в памяти. Прямо мистика какая то. sm.gif
Прикрепленное изображение


Сообщение отредактировал flopix - Jan 25 2013, 21:15
Go to the top of the page
 
+Quote Post
Allregia
сообщение Jan 25 2013, 21:19
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Помоему, правильнее делать не
fh->sfBand = &sfBandTable[0][0];
а
fh.sfBand = &sfBandTable[0][0];
Go to the top of the page
 
+Quote Post
KRS
сообщение Jan 25 2013, 22:38
Сообщение #3


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(Allregia @ Jan 26 2013, 01:19) *
Помоему, правильнее делать не
fh->sfBand = &sfBandTable[0][0];
а
fh.sfBand = &sfBandTable[0][0];

логично!
А разве компилятор С не должен в данном случае вывести ошибку?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 25 2013, 22:43
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (flopix @ Jan 25 2013, 23:10) *
В одной из функций объявляется небольшой массив
Очень похоже на нехватку стека. И размещаемые на нем автоматические переменные "наползают" на глобальные. Чему равен указатель стека в этой функции? На каком адресе заканчиваются переменные (видно в .map-файле)?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
flopix
сообщение Jan 26 2013, 05:39
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 105
Регистрация: 21-06-12
Пользователь №: 72 429



Цитата(Allregia @ Jan 25 2013, 23:19) *
Помоему, правильнее делать не
fh->sfBand = &sfBandTable[0][0];
а
fh.sfBand = &sfBandTable[0][0];

Это строки из библиотеки Helix, не думаю что в ней может быть ошибка.

Цитата(Сергей Борщ @ Jan 26 2013, 00:43) *
Очень похоже на нехватку стека. И размещаемые на нем автоматические переменные "наползают" на глобальные. Чему равен указатель стека в этой функции? На каком адресе заканчиваются переменные (видно в .map-файле)?

При входе в функцию, еще до инициализации переменных регистр R13(SP) = 0x20012378, после инициализации R13(SP) = 0x200122F8.
Правда в этот раз именно в этой функции массив не испортило, это произошло в какой то из вызываемых далее функции.

Как посмотреть в map файле где заканчиваются переменные не понял, поэтому прикрепил сам map файл.

Сообщение отредактировал flopix - Jan 26 2013, 08:02
Прикрепленные файлы
Прикрепленный файл  MEDIA_USB_KEY.zip ( 42.52 килобайт ) Кол-во скачиваний: 34
 
Go to the top of the page
 
+Quote Post
HHIMERA
сообщение Jan 26 2013, 07:19
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126



Не парьте мозг...
Если массив наезжает на структуру, то дело в структуре...
Разбирайтесь с размерностью всех элементов...
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jan 26 2013, 09:03
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Привет!

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

выглядит это так.
передаем в функцию указатель на массив. Внутри функции указатель меня адрес (что очень странно), по новому адресу заполняются данные верные, по старому ничего нет, выходя из функции, данных нет не там не там. По старому адресу нули или мусор, или часть данных. Но если данные присваивать и сравнивать все работает правильно.

То есть это именно глюк отображения значения переменных кеилом при дебуге. По стилю разработки редко пользуюсь внутрисхемными отладчиками, но тут мне так нахваливали удобство что поддался, час втыкал где могла быть ошибка с указателями и что я не так написал. А потом понял ошибка отображения...

Решается так, если очень надо знать значения.
1. надо создать локальную переменную не массив и присвоить ей значения одного элемента, тогда его значение будет отображено корректно
2. можно создать глобальный массив, и его заполнять или использовать, тогда опять же отображение будет корректно.
3. создать указатель на массив, присвоить ему значение указывающие на начало массива, тогда поэлементно можно будет просмотреть весь массив

все прочие способы договорится с дебугером - минное поле, то сработают то нет. Может у вас происходит та же хрень? то есть просто глюк отображения?


По поводу -> и . По идее стрелка должна работать только с указателями на структуру. Но с другой стороны имя структуры является указателем на нее, как имя массива чаров является чаровым указателем. Скорее всего кеил делает неявную подмену имени на указатель, и потому разрешает вызывать его по стрелке. Но строго говоря это не верно и может приводить к ошибкам.
Например кеил не имея явно описанного прототипа функции заменяет все типы переменных на инты, и вызывает крайне странные глюки работы функции. Потому в этом деле лучше перебдеть чем потом ловить ошибки.

А насчет того что там не может быть ошибок - наивно, очень много файлов в начале имеет десклаймер, где написано что предоставляются с целью ознакомления, клиентам для ускорения разработки, не могут использовать коммерчески, все проблемы по вине ошибок исходников не рассматриваются. Так что решайте сами...
Go to the top of the page
 
+Quote Post
Allregia
сообщение Jan 26 2013, 10:47
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Цитата(flopix @ Jan 26 2013, 07:39) *
Это строки из библиотеки Helix, не думаю что в ней может быть ошибка.


Тогда я чего-то не понимаю в Си.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 26 2013, 10:49
Сообщение #9


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (flopix @ Jan 26 2013, 07:39) *
Как посмотреть в map файле где заканчиваются переменные не понял, поэтому прикрепил сам map файл.

CODE
Image Symbol Table

    Local Symbols

    Symbol Name                              Value     Ov Type        Size  Object(Section)
.....
    LfnBuf                                   0x2000c416   Data         512  ff.o(.bss)
    .bss                                     0x2000c618   Section    23816  buffers.o(.bss)
    STACK                                    0x20012320   Section     1024  startup_stm32f4xx.o(STACK)

Как видите, ваш стек начинается с адреса 0x20012320 и занимает 1024 байта. Указатель стека после входа в функцию 0x200122F8, то есть вышел за пределы выделеной памяти и портит значения какой-то переменной из файла buffers.o. Увеличивайте стек. А если можете - измените скрипт линкера и startup_stm32f4xx так, чтобы указатель стека устанавливался на конец ОЗУ. Если же уже сейчас так и сделано - придется переписывать программу, сокращая количество больших автоматических переменных - стараться не использовать автоматические массивы и структуры большого размера.

Добавлено: посмотрел .map дальше:
CODE
    Global Symbols

    Symbol Name                              Value     Ov Type        Size  Object(Section)
......
    fh                                       0x200122e8   Data          56  buffers.o(.bss)
    __initial_sp                             0x20012720   Data           0  startup_stm32f4xx.o(STACK)
Как видите, указатель стека инициализируется адресом конца массива STACK и в указанной функции протит переменную fh. Увеличивайте стек или в startup_stm32f4xx ставьте его на конец ОЗУ (адрес конца ОЗУ может дать скрипт линкера). Тогда забудете об этой проблеме до того момента, пока ОЗУ не будет использовано действительно полностью.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jan 26 2013, 11:03
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Цитата(Allregia @ Jan 26 2013, 14:47) *
Тогда я чего-то не понимаю в Си.


кстати может там и ошибка, но скрытая

str->field - равносильно
(*str).field, при этом при некоторых заполнениях структуры особой беды не будет
так как str - это указатель на первое поле структуры, если в этом поле лежит значение равное адресу расположения структуры то вообще никакой беды не будет. А если значение далекое от всех данных, то просто где то в оперативке фактически появляется структура, и пока на нее не залезут данные все будет работать.
Go to the top of the page
 
+Quote Post
flopix
сообщение Jan 26 2013, 19:17
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 105
Регистрация: 21-06-12
Пользователь №: 72 429



Действительно, увеличил размер стека с 0x400 до 0x1000 - все заработало sm.gif. Всем спасибо за помощь.

Тогда уж еще вопрос, как правильно выбирать размер стека, чем руководствоваться чтобы потом не ловить такие трудно находимые глюки?
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jan 26 2013, 19:30
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



картой памяти,
так же как сейчас, кроме как следить за этим других вариантов нет.

проверьте все же где в памяти лежит та структура
и одинаково ли ведет себя программа если -> на . заменить...

Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 11:03
Рейтинг@Mail.ru


Страница сгенерированна за 0.01466 секунд с 7
ELECTRONIX ©2004-2016