|
Снова о gcc и невыровненном доступе к памяти |
|
|
|
Jun 28 2011, 07:29
|
Группа: Новичок
Сообщений: 4
Регистрация: 6-05-09
Пользователь №: 48 742

|
Знаю что такие темы уже были, тем не менее я так и не разобрался как сделать лучше и проще всего Есть Atmel AT91RM9200, на котором крутится Linux, и на который надо портировать софтинку, в которой есть необходимость обращаться к элементам структуры типа:
struct blabla { char ch; int that; } blabla_t
При обращении к that и происходит, собсно, невыровненный доступ к памяти. При этом объявить структуру с параметром __attribute__ ((__aligned__(4))), или дополнить паддингом я не могу, ибо по сети приходит пакет, на который собсно и накладывается структура. Да и отловить все подобные обращения в сотне исходный файлов не представляется оптимальным путём.
Собственно, вопрос, как быть? Неужели нет простой возможности обойти проблему в банальнейшей операции обращения к полю структуры?
И еще одна непонятка. Вроде бы бит A в CP15 включен, однако никаких исключений при таких обращения не происходит. Поэтому я даже не могу узнать о таком обращении. ЧЯДНТ? Может, надо еще что то где то включить? Или в линухе реализована обработка подобного исключения но у меня она почему то не работает?
Всем спасибо!
|
|
|
|
|
 |
Ответов
|
Jun 28 2011, 07:40
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(vinni-puch @ Jun 28 2011, 11:29)  Или в линухе реализована обработка подобного исключения но у меня она почему то не работает? У меня на работе стоит компьютер Sparc 64-bit с линуксом. Там логи засыпаны сообщениями о невыравненном доступе к памяти. Виновник - модуль cifs, т.е. часть ядра линукс. Очевидно, ядро перехватывает невыравненные обращения к памяти и прозрачным образом их обрабатывает. Ну а пейсатели модуля cifs, очевидно, не парятся и полагаются на эту фичу ядра. Мне кажется, у Вас должна быть та же фича. Update: Кстати, в исходниках модуля cifs можете и подсмотреть, как они объявляют такие структуры: cifspdu.h
|
|
|
|
|
Jun 28 2011, 08:04
|
Группа: Новичок
Сообщений: 4
Регистрация: 6-05-09
Пользователь №: 48 742

|
Ребят, по факту у меня ЕСТЬ невыровненное обращение, и по умолчанию компилятор ничего не выравнивает. Т. е. типа __attribute__((packed)) Я очень долго искал в чем же бага, потому что у меня не было ни одного сообщения о невыровненности, (опять же, почему их нет?) потом написал вырожденный случай в 10 строк, который работает неправильно - именно из-за невыровненности.
Так вот вопрос в этом и состоит, что как и где сказать компилятору, что обращения к этой структуре будут невыровненны. так чтобы внести минимальное кол-во исправлений в код. Но не пользуясь атрибутом aligned, потому что это изменяет физический размер структуры, а я привязан к формату кадра. Или как заставить линукс эти невыровненные обращения подменять сложными чтениями/сдвигами, чтобы для меня это вообще прозрачно было. Ведь не валится ничего!
|
|
|
|
|
Jun 28 2011, 08:11
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(vinni-puch @ Jun 28 2011, 12:04)  Ребят, по факту у меня ЕСТЬ невыровненное обращение, и по умолчанию компилятор ничего не выравнивает. Т. е. типа __attribute__((packed)) Откуда инфа? Может быть, Вам показалось? Цитата(vinni-puch @ Jun 28 2011, 12:04)  Я очень долго искал в чем же бага, потому что у меня не было ни одного сообщения о невыровненности, (опять же, почему их нет?) потом написал вырожденный случай в 10 строк, который работает неправильно - именно из-за невыровненности. Опять же, может Вам показалось? Напишите подробнее. Цитата(vinni-puch @ Jun 28 2011, 12:04)  Так вот вопрос в этом и состоит, что как и где сказать компилятору, что обращения к этой структуре будут невыровненны. так чтобы внести минимальное кол-во исправлений в код. Но не пользуясь атрибутом aligned, потому что это изменяет физический размер структуры, а я привязан к формату кадра. Неприлично не читать ответы на вопросы. См. выше: содержимое файла cifspdu.h.
|
|
|
|
|
Jun 28 2011, 09:04
|
Группа: Новичок
Сообщений: 4
Регистрация: 6-05-09
Пользователь №: 48 742

|
Цитата(scifi @ Jun 28 2011, 11:11)  Неприлично не читать ответы на вопросы. См. выше: содержимое файла cifspdu.h. Было бы неприлично, если бы не читал. Ан нет  Вы же сами сказали что у вас валятся ошибки этого модуля. Т.е. он заведомо написан неверно. Я посмотрел, там действительно все структуры объявляются с атрбиутом packed. НО этот атрибут делает заведомо наоборот от того что мне нужно, поэтому там все так и работает. В качестве док-ва прилагаю тестовую програмку и ЛОГ, в котором видно что работает она неправильно, можете сравнить ее вывод с тем, что даст вам хостовый компутер. Видно так же, почему мне не подходят все эти манипуляции с атрибутами структуры К сожалению загружать файлы мне запрещено, вставляю в тело И, отвечая частично на свой вопрос - сообщения не вываливались, потому что есть такой файл как /proc/cpu/alignment, По дефолту ничего не делается. Если записать туда 1 - будет лог. Если 2 - то будет фиксить. В логе видно, что это действительно работает. Програмка: CODE #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h>
typedef struct bpdu_body_y { unsigned char flags; unsigned char root_id[8]; unsigned char root_path_cost[4]; unsigned char bridge_id[8]; unsigned char port_id[2]; unsigned char message_age[2]; unsigned char max_age[2]; unsigned char hello_time[2]; unsigned char forward_delay[2]; } BPDU_BODY_Y;
typedef struct bpdu_body_t { unsigned char flags; unsigned char root_id[8]; unsigned char root_path_cost[4] __attribute__ ((__aligned__(4))); unsigned char bridge_id[8]; unsigned char port_id[2]; unsigned char message_age[2]; unsigned char max_age[2]; unsigned char hello_time[2]; unsigned char forward_delay[2]; } __attribute__ ((__aligned__(4))) BPDU_BODY_T;
int main(int argc, char *argv[]) { int i; volatile char *memo; volatile u32 *imemo; BPDU_BODY_T *bmemo; BPDU_BODY_Y *ymemo;
printf ("sizeof unaligned struct = %d; sizeof aligned struct = %d\n", sizeof(BPDU_BODY_Y), sizeof(BPDU_BODY_T));
memo = (char *)malloc(sizeof (BPDU_BODY_T));
for (i = 0; i < sizeof (BPDU_BODY_T); i++) { memo[i] = i; }
printf ("------------------------------------------------------------------------------------------------------\n\t"); bmemo = memo; ymemo = memo; printf ("\tMemory contents: \n\n"); for (i = 0; i < sizeof(BPDU_BODY_T); i++) { printf("%02X", memo[i]); if (!((i+1)%4)) { printf ("|"); } } printf ("\n----------------------------------------------------------------\n"); printf ("It should be %02X%02X%02X%02X\n\n", ymemo->root_path_cost[3], ymemo->root_path_cost[2], ymemo->root_path_cost[1], ymemo->root_path_cost[0]); memo = memo + 9; printf ("Addr of unaligned root_path_cost is %p; Addr of aligned root_path_cost is %p; \n", &ymemo->root_path_cost, &bmemo->root_path_cost); printf("\tUnaligned root_path_cost %08X\n\t", *((int *)(ymemo->root_path_cost))); printf("Aligned root_path_cost %08X\n", *((int *)(bmemo->root_path_cost)));
return 0; }
ЛОГ: CODE root@OpenWrt:/# tst1 sizeof unaligned struct = 31; sizeof aligned struct = 36 ------------------------------------------------------------------------------------------------------ Memory contents:
00010203|04050607|08090A0B|0C0D0E0F|10111213|14151617|18191A1B|1C1D1E1F|20212223 | ---------------------------------------------------------------- It should be 0C0B0A09
Addr of unaligned root_path_cost is 0x11011; Addr of aligned root_path_cost is 0x11014; Unaligned root_path_cost 080B0A09 Aligned root_path_cost 0F0E0D0C root@OpenWrt:/# echo 2 > /proc/cpu/alignment root@OpenWrt:/# tst1 sizeof unaligned struct = 31; sizeof aligned struct = 36 ------------------------------------------------------------------------------------------------------ Memory contents:
00010203|04050607|08090A0B|0C0D0E0F|10111213|14151617|18191A1B|1C1D1E1F|20212223 | ---------------------------------------------------------------- It should be 0C0B0A09
Addr of unaligned root_path_cost is 0x11011; Addr of aligned root_path_cost is 0x11014; Unaligned root_path_cost 0C0B0A09 Aligned root_path_cost 0F0E0D0C
|
|
|
|
|
Jun 28 2011, 12:01
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (vinni-puch @ Jun 28 2011, 11:04)  Програмка: Не сочли нужным объявить, что структура BPDU_BODY_Y пакованная. Что написали, то и получили. QUOTE (Petka @ Jun 28 2011, 10:58)  как-то так =) Совершенно дикие действия  с трудноуловимым смыслом  .
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 28 2011, 13:46
|
Профессионал
    
Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886

|
Цитата(zltigo @ Jun 28 2011, 16:01)  Совершенно дикие действия  с трудноуловимым смыслом  . Что в них "дикого"? Если смысл непонятен, поясню: Если информационный пакет пришёл по "сети" или из другого источника, когда не гарантируется что данные будут располагаться в памяти выровнено или когда Endianness отсылающей стороны может не совпасть с получателем. Тогда есть только одна возможность считывать поля структуры из памяти - побайтно, а потом собирать байты в слова. Описанный выше механизм позволяет из произвольно расположенной структуры в памяти вычитывать последовательно с гарантированно одинаковым результатом независимо от архитектуры, компиляторов и всяческих выравниваний. Разумеется, когда структура заполняется и пересылается в рамках одного вычислителя, то этот метод избыточен. Так понятней?
|
|
|
|
|
Jun 28 2011, 14:46
|
Профессионал
    
Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886

|
Цитата(KRS @ Jun 28 2011, 17:51)  Да все было и так понятно! Не понятно зачем городить этот огород, не проще ли взять современный компилятор и объяснить ему что, где и в каком порядке лежит! Тогда код будет и понятнее и оптимальнее  потому что есть инструкции чтения с переворотом и т.п. Прошу в студию код, как "правильно" объявить структуру blabla у ТС для gcc. Цитата(zltigo @ Jun 28 2011, 18:05)  KRS все уже объяснил, почему делать так, как Вы сделали, неразумно. Только что проверил. Код uint8_t msg[] __attribute__ ((aligned (16))) = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A };
struct blabla_t { char ch; int that __attribute__((packed)); } __attribute__((packed)); struct blabla_t *bla;
int a;
bla=&msg[3]; a = bla->that; printf("a = 0x%08X\n", a);
bla=&msg[0]; a = bla->that; printf("a = 0x%08X\n", a); результат: Код a = 0x08070605 Ошибка шины Итог: никакие "#pragma packed" вам не помогут! Вот теперь понятно? P.S. Я включил в системе контроль alignment. "Ошибка шины" это "SIGBUS" - и есть ошибка невыровненного доступа.
|
|
|
|
|
Jun 28 2011, 15:22
|

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

|
Цитата(Petka @ Jun 28 2011, 18:46)  Итог: никакие "#pragma packed" вам не помогут! Вот теперь понятно? Ну вам не помогают, а мне помогают Код #include <stdint.h> #include <stdio.h>
#pragma pack(1) typedef struct { char ch; int that; } blabla_t; #pragma pack()
void test(blabla_t *bla) { printf("a = 0x%08X\n", bla->that); }
uint8_t msg[] __attribute__ ((aligned (16))) = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A }; void test2(void) { blabla_t *bla;
int a;
bla= (blabla_t *)&msg[3]; a = bla->that; printf("a = 0x%08X\n", a);
bla=(blabla_t *)&msg[0]; a = bla->that; printf("a = 0x%08X\n", a); } По листингу все читается по байтам, так что все ок! Все таки надо использовать typedef и при присваивании преобразовывать указатели, что бы не плодить warningи, на которые стоит обращать внимание!
|
|
|
|
Сообщений в этой теме
vinni-puch Снова о gcc и невыровненном доступе к памяти Jun 28 2011, 07:29 KRS Цитата(vinni-puch @ Jun 28 2011, 11... Jun 28 2011, 07:36 zltigo QUOTE (vinni-puch @ Jun 28 2011, 09... Jun 28 2011, 07:38    scifi Цитата(vinni-puch @ Jun 28 2011, 13... Jun 28 2011, 09:27         Petka Цитата(KRS @ Jun 28 2011, 19:22) Ну вам н... Jun 28 2011, 16:00          KRS Цитата(Petka @ Jun 28 2011, 20:00) Давайт... Jun 28 2011, 16:05           Petka Цитата(KRS @ Jun 28 2011, 20:05) И при че... Jun 28 2011, 16:18            zltigo QUOTE (Petka @ Jun 28 2011, 18:18) P.S. В... Jun 28 2011, 16:54            KRS Цитата(Petka @ Jun 28 2011, 20:18) Да, пр... Jun 28 2011, 17:36      zltigo QUOTE (Petka @ Jun 28 2011, 15:46) Так по... Jun 28 2011, 14:05  zltigo QUOTE (vinni-puch @ Jun 28 2011, 10... Jun 28 2011, 08:21 Petka Цитата(vinni-puch @ Jun 28 2011, 11... Jun 28 2011, 08:58 KRS Цитата(Petka @ Jun 28 2011, 12:58) Кодcha... Jun 28 2011, 10:01  Petka Цитата(KRS @ Jun 28 2011, 14:01) Зато мож... Jun 28 2011, 10:45   KRS Цитата(Petka @ Jun 28 2011, 14:45) 2) Вся... Jun 28 2011, 13:42 VladislavS Если компилятор сам расположил структуру в памяти,... Jun 28 2011, 17:43
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|