|
Снова о gcc и невыровненном доступе к памяти |
|
|
|
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и, на которые стоит обращать внимание!
|
|
|
|
|
Jun 28 2011, 16:00
|
Профессионал
    
Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886

|
Цитата(KRS @ Jun 28 2011, 19:22)  Ну вам не помогают, а мне помогают .... По листингу все читается по байтам, так что все ок! Все таки надо использовать typedef и при присваивании преобразовывать указатели, что бы не плодить warningи, на которые стоит обращать внимание! Давайте разбираться: Собрал ваш код gcc (4.5.2, "-O0"). Ошибка доступа ЕСТЬ! Код objdump -d -S ./a.out Вывод: Код 080483e3 <test2>:
uint8_t msg[] __attribute__ ((aligned (16))) = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A };
void test2(void) { 80483e3: 55 push %ebp 80483e4: 89 e5 mov %esp,%ebp 80483e6: 83 ec 28 sub $0x28,%esp blabla_t *bla;
int a;
bla= (blabla_t *)&msg[3]; 80483e9: b8 20 a0 04 08 mov $0x804a020,%eax 80483ee: 83 c0 03 add $0x3,%eax 80483f1: 89 45 f4 mov %eax,-0xc(%ebp) a = bla->that; 80483f4: 8b 45 f4 mov -0xc(%ebp),%eax 80483f7: 8b 40 01 mov 0x1(%eax),%eax 80483fa: 89 45 f0 mov %eax,-0x10(%ebp) printf("a = 0x%08X\n", a); 80483fd: b8 20 85 04 08 mov $0x8048520,%eax 8048402: 8b 55 f0 mov -0x10(%ebp),%edx 8048405: 89 54 24 04 mov %edx,0x4(%esp) 8048409: 89 04 24 mov %eax,(%esp) 804840c: e8 e3 fe ff ff call 80482f4 <printf@plt>
bla=(blabla_t *)&msg[0]; 8048411: c7 45 f4 20 a0 04 08 movl $0x804a020,-0xc(%ebp) a = bla->that; 8048418: 8b 45 f4 mov -0xc(%ebp),%eax 804841b: 8b 40 01 mov 0x1(%eax),%eax 804841e: 89 45 f0 mov %eax,-0x10(%ebp) printf("a = 0x%08X\n", a); 8048421: b8 20 85 04 08 mov $0x8048520,%eax 8048426: 8b 55 f0 mov -0x10(%ebp),%edx 8048429: 89 54 24 04 mov %edx,0x4(%esp) 804842d: 89 04 24 mov %eax,(%esp) 8048430: e8 bf fe ff ff call 80482f4 <printf@plt> } 8048435: c9 leave 8048436: c3 ret И где тут по-байтное обращение?
|
|
|
|
|
Jun 28 2011, 16:18
|
Профессионал
    
Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886

|
Цитата(KRS @ Jun 28 2011, 20:05)  И при чем здесь ARM? Интел умеет читать по не выравненному адресу, зачем читать по байтам? Может, но не обязан. (См. eFlags, бит 18) Цитата(KRS @ Jun 28 2011, 20:05)  И при чем здесь ARM? Да, проверил на ARM. Действительно читает по-байтно. P.S. Вот бы ещё ссылку на стандарт какой.
|
|
|
|
|
Jun 28 2011, 16:54
|

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

|
QUOTE (Petka @ Jun 28 2011, 18:18)  P.S. Вот бы ещё ссылку на стандарт какой. Причем тут стандарт? Что Вы хотите увидеть? Большими красными буквами "Компилятор языка 'C' обязан уметь корректно работать со структурами данных"? Есть структура данных, Вы полно и корректно описали, что она из себя представляет. Все, любой компилятор обязан правильно работать. Зачем указывать отдельно, например, в ГОСТ на автомобиль, то, что должен уметь перемещаться и без запряженной лошади? И уж тем более, не стоит ее в автомобиль запрягать, даже если в ГОСТ на него не написано, что лошадь не требуется.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 28 2011, 17:36
|

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

|
Цитата(Petka @ Jun 28 2011, 20:18)  Да, проверил на ARM. Действительно читает по-байтно. А хороший компилер, в случае с bla= (blabla_t *)&msg[3]; a = bla->that; должен читать сразу слово! (при соотв. уровне оптимизации) потому что в данном случае возможно проследить выравнивание. И, например, RVCT так и делает!
|
|
|
|
|
Jun 28 2011, 17:43
|
Местный
  
Группа: Свой
Сообщений: 475
Регистрация: 14-04-05
Из: Москва
Пользователь №: 4 140

|
Если компилятор сам расположил структуру в памяти, то вне зависимости от директивы pack он должен корректно обращаться к памяти при доступе к любому полю. А вот если с указателями работать вольно, то запросто можно схлопотать ошибку доступа. Или вот так  Код *((int *)0x40000007)=0;
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|