haker_fox 61 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба Поторопился с выводом. Даже с __packed падает((( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MasterElectric 0 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба Для доступа к байту выравнивать не нужно, для полуслова адрес должен быть кратен 2, для слова 4 байтам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба 51 minutes ago, MasterElectric said: Для доступа к байту выравнивать не нужно, для полуслова адрес должен быть кратен 2, для слова 4 байтам. Это же указатель на массив из байт. Я вот и не могу понять, нужно ли массиву указывать это слово. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба packed необходим для того чтобы соответствующим образом разложить поля в структуре, ключевое слово __packed разлаживает поля "плотничком", но упакованная структура может лежать по не выровненному адресу! для того чтобы положить данные по кратному адресу, в IAR например, используется конструкция #pragma data_alignment =4 #pragma data_alignment = 4 uint8_t ptr1[128]; uint8_t ptr2[128]; memcpy( ptr1, ptr2, 128); Но, Вы используете new, и он судя по всему он отдает вам адрес не кратный 4. К сожалению не могу сказать как заставить new сделать это, нужно смотреть в документацию на ваши инструменты разработки Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба 1 час назад, haker_fox сказал: Я так понимаю, это невыровненный доступ. Нет конечно. Причём тут невыровненный доступ, если аргументы-указатели функции (memcpy()) могут быть произвольными (байтовыми)? Скорее похоже на то, что Ваш memcpy() лезет в несуществующую память (нарушение границ). Смотрите код в точке fault-а и значение регистров в этой точке. Как вариант: один из ваших new не может выделить память и возвращает NULL, который Вы затем передаёте в memcpy(). Отсюда и доступ в несуществующую память. Почему после new не проверяете возвращаемое ею значение? Это грубая ошибка. Вообще эта ошибка находится за 5 минут, после взгляда в окна дизасма и состояния регистров отладчика. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба 12 minutes ago, jcxz said: Нет конечно. Причём тут невыровненный доступ, если аргументы-указатели функции (memcpy()) могут быть произвольными (байтовыми)? Скорее похоже на то, что Ваш memcpy() лезет в несуществующую память (нарушение границ). Смотрите код в точке fault-а и значение регистров в этой точке. Как вариант: один из ваших new не может выделить память и возвращает NULL, который Вы затем передаёте в memcpy(). Отсюда и доступ в несуществующую память. Почему после new не проверяете возвращаемое ею значение? Это грубая ошибка. Вообще эта ошибка находится за 5 минут, после взгляда в окна дизасма и состояния регистров отладчика. Соглашусь, проблема скорее не в выравнивании, на Cortex-M4F такое сложно сделать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба 17 minutes ago, jcxz said: Почему после new не проверяете возвращаемое ею значение? Это грубая ошибка. Простите, это я код некорректно привёл. Указатель на null проверяется. Там всё ок. А на счёт выравнивания меня эта статья смутила. Там написано, что __aeabi_memcpy4 ожидает выровненных указателей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба 1 hour ago, haker_fox said: А на счёт выравнивания меня эта статья смутила. В данном примере, вероятно, ключевой момент был в (void *)packed_ptr, после этого компилятор будет использовать байтовый __aeabi_memcpy #include <string.h> unsigned int * const dest; void example (unsigned int * const unaligned_ptr) { __packed unsigned int * packed_ptr = unaligned_ptr; char * temp_ptr = (char *)unaligned_ptr; memcpy(dest, unaligned_ptr, 32); /* Unsafe */ memcpy(dest, (void *)packed_ptr, 32); /* Safe */ memcpy(dest, temp_ptr, 32); /* Safe */ } Не совсем понятно какую цель они преследовали добавив туда __packed, возможно что-бы явно показать что packed_ptr может быть не выровнен, о чем можно прочитать здесь Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба 2 hours ago, Integro said: Не совсем понятно какую цель они преследовали добавив туда __packed, возможно что-бы явно показать что packed_ptr может быть не выровнен, о чем можно прочитать здесь Там же написано: You need to either explicitly tell the compiler when you are using unaligned pointers by using the __packed keyword (described in the compiler guide), or create a temporary char* pointer to access the address. Что здесь непонятно? Но вообще там корень проблемы в том, что указатель на int прямо на входе в функцию уже невыравненный. По феншую нужно исправлять тип указателя, чтобы соответствовал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Integro 0 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба 2 minutes ago, scifi said: По феншую нужно исправлять тип указателя, чтобы соответствовал. Cмысл исправлять на __packed если они потом приводят к типу (void*) ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба 25 minutes ago, Integro said: Cмысл исправлять на __packed если они потом приводят к типу (void*) ? Явное приведение к void*, очевидно, нужно лишь для того, чтобы подавить предупреждение компилятора. Всё равно оно неявно приведётся к тому же void* перед вызовом функции (см. объявление memcpy). Кстати, стандарт говорит, что неопределённое поведение возникает в момент, когда указателю присваивают значение без нужного выравнивания. В примере, который приводит Арм, это происходит до вызова функции example(). В этом смысле пример плохой, так как исправляет последствия косяка и как бы поощряет неокрепшие умы забить на первопричину. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба 4 hours ago, jcxz said: Вообще эта ошибка находится за 5 минут, после взгляда в окна дизасма и состояния регистров отладчика Я так понимаю вприглядку на стандарт AEABI? Чтобы понять, в каких регистрах какие аргументы расположены... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба 29 минут назад, haker_fox сказал: Я так понимаю вприглядку на стандарт AEABI? Чтобы понять, в каких регистрах какие аргументы расположены... Зачем? Точку фаулта (PC) знаете? Смотрите в окно дизасма на команды в этом месте и в окно регистров на их значения, и определяете причину. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба 1 minute ago, jcxz said: Зачем? Точку фаулта (PC) знаете? Кстати, насколько мне известно, она не всегда же валидна. Об этом на сайте arm.com написано. Насколько помню там нужно анализировать HFSR или подобный регистр. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 234 16 ноября, 2018 Опубликовано 16 ноября, 2018 · Жалоба 1 час назад, haker_fox сказал: Кстати, насколько мне известно, она не всегда же валидна. Об этом на сайте arm.com написано. Насколько помню там нужно анализировать HFSR или подобный регистр. Так вроде Вы написали, что анализируете: 8 часов назад, haker_fox сказал: В отладчике HF у меня есть анализ регистров, и причина указан "A data bus error has occurred". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться