|
Переменная по адресу не кратному 4 байт. |
|
|
|
Sep 12 2018, 15:29
|
Частый гость
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008
|
Всем привет, наткнулся на такой баг - объявил буфер в глобальных переменных. Передаю его адрес в аргументе функции. И когда обращаюсь в функции к этой переменной через указатель сразу вылетаю в HardFault_Handler. Пол дня парился, и в конце концов выяснил, что линковщик расположил ее по адресу не кратному 4. Проверил, действительно если передать в функцию указатель не кратный 4, то при чтении по этому адресу вылетаем в HardFault_Handler. И теперь не могу добиться, чтоб этот буфер разместился по корректному адресу. Добавляю перед ним или после него новые переменные, адреса смещаются, и у него все равно адрес не корректный. Что делать? P.S Keil V5.23.0.0
|
|
|
|
|
Sep 12 2018, 15:33
|
Профессионал
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831
|
Цитата(maxntf @ Sep 12 2018, 18:29) линковщик расположил ее по адресу не кратному 4 Сейчас принято делать так: http://www.keil.com/support/man/docs/armcc...59124981436.htmно раньше делали так: http://www.keil.com/support/man/docs/armcc...59124966304.htmИ укажите версию компилятора. Keil умеет работать с разными компиляторами, в комплекте к нему нынче идут ДВА встроенных РАЗНЫХ, и даже можно подключить внешний (GNU например)
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Sep 12 2018, 15:35
|
Гуру
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095
|
QUOTE (maxntf @ Sep 12 2018, 18:29) Что делать? 1) Уменьшить картинку, чтобы страница форума не расползалась. 2) Показать объявление этого буфера.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 13 2018, 08:21
|
Профессионал
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831
|
Цитата(Kabdim @ Sep 13 2018, 11:10) Скопировать значение в выравненную переменную с помощью memcpy. Вызвать функцию с этой локальной переменной. (опционально)Скопировать значение назад. Это и есть пуленепробиваемое решение которое работает везде, независимо от типов и версий компиляторов и языка. Ваш совет - один из лидеров среди самых вредных и опасных советов Кстати, memcpy - очень коварный костыль! Любой компилятор умеет "говорить" о том, какой он и даже "назвать" свою версию. Ничто не мешает использовать эту информацию в своем коде для учета особенностей разных компиляторов, если есть нужда в поддержки разных компиляторов. Пример реально пуленепробиваемого решения: Код // Arm Compiler v5 #if defined ( __CC_ARM )
#pragma import(__use_no_heap) #pragma import(__ARM_use_no_argv) #pragma import(__use_two_region_memory)
// Arm Compiler v6 #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
__asm(".global __use_no_heap \n\t"); __asm(".global __ARM_use_no_argv \n\t"); __asm(".global __use_two_region_memory \n\t");
#endif
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Sep 13 2018, 08:55
|
Частый гость
Группа: Участник
Сообщений: 107
Регистрация: 13-05-09
Пользователь №: 49 008
|
Цитата(Forger @ Sep 12 2018, 18:33) Спасибо, понял в чем тут дело. Просто раньше работал только с 8 битными МК, там таких проблем нет. А у меня получилось, что буфер char - выравнивание у него по одному байту (без атрибута, начинаться может с любого адреса), а в качестве аргумента функции я передаю указатель на этот буфер с приведением типа до uint32.
Сообщение отредактировал maxntf - Sep 13 2018, 09:00
|
|
|
|
|
Sep 13 2018, 09:03
|
Гуру
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136
|
Цитата(Сергей Борщ @ Sep 12 2018, 18:35) 2) Показать объявление этого буфера. +1. Сначала надо не костылями подпирать, а разобраться, в чём первопричина проблемы. Цитата(maxntf @ Sep 13 2018, 11:55) А у меня получилось, что буфер char - выравнивание у него по одному байту (без атрибута, начинаться может с любого адреса), а в качестве аргумента функции я передаю указатель на этот буфер с приведением типа до uint32. Это ужасно. Костыль в виде aligned вылечит, но ужас никуда не денется.
|
|
|
|
|
Sep 13 2018, 10:17
|
Профессионал
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831
|
Цитата(scifi @ Sep 13 2018, 12:03) Костыль в виде aligned вылечит, но ужас никуда не денется. Ну-ну, попробуйте объявить массив для стека какой-нить задачи RTOS, НЕ применив к нему обязательный "костыль" aligned. ... "Ужас" убирается объявлением вместо банальных байтовых массивов с разношерстными данными ("протокольные" дела) объявлением полноценных структур с полями нужных размеров и названий, даже с применением union, где это нужно. Чтобы структура была одинакового размера на любых компиляторах, нужен атрибут packed. Это - норма. После чего в соотв. функцию передается ссылка (&) на структуру (или указатель, если нельзя писать на плюсах). В этом случае правильный доступ к полям структуры станет головной болью компилятора, а не кодера. Вот пример обяявления такой структуры (не самый лучший пример, но тем не менее): Код struct __PACKED Frame { uint8_t start; uint8_t command; uint8_t dataSize; union { uint8_t payload[COMMUNICATION_MAX_FRAME_DATA_SIZE_IN_BYTES]; MasterToSlave masterToSlave; SlaveToMaster slaveToMaster; } data; struct { union { struct { uint8_t low; uint8_t high; }; uint16_t value; }; } crc16; };
// SlaveToMaster и SlaveToMaster - структуры одинакового размера, но с разными полями ps. из-за необходимости применения телепатии к стартовому посту эта тема рискует перейти в очередной холивар :D
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Sep 13 2018, 14:55
|
Знающий
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842
|
Цитата(Forger @ Sep 13 2018, 11:21) Ваш совет - один из лидеров среди самых вредных и опасных советов Кстати, memcpy - очень коварный костыль! Пруфов, я так понимаю, дождаться нереально? Цитата(Forger @ Sep 13 2018, 11:21) Пример реально пуленепробиваемого решения: Гы!
|
|
|
|
|
Sep 13 2018, 15:15
|
Профессионал
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831
|
Цитата(Kabdim @ Sep 13 2018, 17:55) Пруфов, я так понимаю, дождаться нереально? Вы правы - это бесполезный пруф из разряда: почему нужно мыть руки перед едой или чистить зубы. Это знают даже дети Во многих уважающих себя конторах это "наследие" вообще давно запрещено к применению. Хотя в примитивном коде, который ни за что не отвечает или служит чисто образовательным целям (ардуины), memcpy в целом беды не несет, разве что кроме впустую потраченных нервов и времени
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Sep 14 2018, 07:47
|
Профессионал
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831
|
Цитата(scifi @ Sep 14 2018, 09:40) Скажем, lwip делает это легко и непринуждённо. Не пойму, при чем тут lwip? Ядро ARM требуют выравнивание стеков по границе 8 байт, иначе вылетаем в HF. Не вижу никакой сложности использовать встроенное расширение компилятора, которое полностью устраняет эту "проблему". Тем более компилятор v6 от ARM практически полностью поддерживает расширения GCC (в отличие от v5, который в целом устарел и поэтому лишь частично умеет это делать). Цитата Нужно выравнивать по 4 байта? Прибавь к размеру массива 3 байта, а указатель отрихтуй до ровного. Соревнуетесь с Kabdim по вредности "советов"?
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Sep 14 2018, 08:56
|
Знающий
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842
|
Цитата(Forger @ Sep 13 2018, 18:15) Вы правы - это бесполезный пруф из разряда: почему нужно мыть руки перед едой или чистить зубы. Это знают даже дети Потому что пруфы для мытья рук есть и если не заниматься демагогией их несложно найти. Цитата(Forger @ Sep 13 2018, 18:15) Во многих уважающих себя конторах это "наследие" вообще давно запрещено к применению. И видимо что бы запретить совсем уж всю идею копирования памяти в другое место они придумали memcpy_s... Цитата(Forger @ Sep 13 2018, 18:15) Хотя в примитивном коде, который ни за что не отвечает или служит чисто образовательным целям (ардуины), memcpy в целом беды не несет, разве что кроме впустую потраченных нервов и времени Ну и к чему эти намеки, если вдруг вы не догадывались, то с Ардуиной я никогда не работал и к образованию кого-либо отношения не имею. Вы мешаете в один чан два разных применения. С буферами переменной длинны где для использования memcpy нужно много проверок и всё зло от того что индусы о ни забывают, а их отсутствие не обеспечивает падение сразу. А с другой стороны копирование переменной фиксированной длинны, где единственная задача убедится что на входе есть данные нужного размера. Если вы тратите на второй вариант использования memcpy нервы и время, могу только посочувствовать. Цитата(Forger @ Sep 14 2018, 10:47) Соревнуетесь с Kabdim по вредности "советов"? Не переживайте, в этом вопросе вы непревзойденный идеал.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|