Перейти к содержанию
    

Снова о gcc и невыровненном доступе к памяти

Так понятней?

Да все было и так понятно! Не понятно зачем городить этот огород, не проще ли взять современный компилятор и объяснить ему что, где и в каком порядке лежит! Тогда код будет и понятнее и оптимальнее ;) потому что есть инструкции чтения с переворотом и т.п.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так понятней?

KRS все уже объяснил, почему делать так, как Вы сделали, неразумно.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да все было и так понятно! Не понятно зачем городить этот огород, не проще ли взять современный компилятор и объяснить ему что, где и в каком порядке лежит! Тогда код будет и понятнее и оптимальнее ;) потому что есть инструкции чтения с переворотом и т.п.

Прошу в студию код, как "правильно" объявить структуру blabla у ТС для gcc.

 

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" - и есть ошибка невыровненного доступа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Итог: никакие "#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и, на которые стоит обращать внимание!

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну вам не помогают, а мне помогают

....

По листингу все читается по байтам, так что все ок!

Все таки надо использовать 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

И где тут по-байтное обращение?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Давайте разбираться:

Собрал ваш код gcc (4.5.2). Ошибка доступа ЕСТЬ!

И при чем здесь ARM?

Интел умеет читать по не выравненному адресу, зачем читать по байтам?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И при чем здесь ARM?

Интел умеет читать по не выравненному адресу, зачем читать по байтам?

Может, но не обязан. (См. eFlags, бит 18)

 

И при чем здесь ARM?

Да, проверил на ARM. Действительно читает по-байтно.

 

P.S. Вот бы ещё ссылку на стандарт какой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

P.S. Вот бы ещё ссылку на стандарт какой.

Причем тут стандарт? Что Вы хотите увидеть? Большими красными буквами "Компилятор языка 'C' обязан уметь корректно работать со структурами данных"?

Есть структура данных, Вы полно и корректно описали, что она из себя представляет. Все, любой компилятор обязан правильно работать.

Зачем указывать отдельно, например, в ГОСТ на автомобиль, то, что должен уметь перемещаться и без запряженной лошади? И уж тем более, не стоит ее в автомобиль запрягать,

даже если в ГОСТ на него не написано, что лошадь не требуется.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, проверил на ARM. Действительно читает по-байтно.

А хороший компилер, в случае с

bla= (blabla_t *)&msg[3];

a = bla->that;

должен читать сразу слово! (при соотв. уровне оптимизации) потому что в данном случае возможно проследить выравнивание. И, например, RVCT так и делает!

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если компилятор сам расположил структуру в памяти, то вне зависимости от директивы pack он должен корректно обращаться к памяти при доступе к любому полю.

 

А вот если с указателями работать вольно, то запросто можно схлопотать ошибку доступа. Или вот так :)

 

*((int *)0x40000007)=0;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...