Выравнивание данных

Тема в разделе "WASM.WIN32", создана пользователем NeuronViking, 17 ноя 2004.

  1. NeuronViking

    NeuronViking New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2004
    Сообщения:
    476
    Адрес:
    где-то в Сиднее
    опять 25, понимаю, но деца от етого никуда не могу ибо затупил конкретно...

    в опчем, как и по каким правилам выравниваюца члены структур данных микрософтовскими компиляторами на платформе IA32? Только с примерами пжалуйста!



    например, имеем следующее:



    #pragma pack( 8 )

    struct x {

    char a;

    DWORD b;

    char c;

    char d;

    };

    #pragma pack()



    пусть:

    x.a = 1;

    x.b = 0x22222222;

    x.c = 3;

    x.d = 4;



    получаем следующее:



    sizeof(x) = 12



    &(x.a) = 0x0012FD24

    &(x.b) = 0x0012FD28

    &(x.c) = 0x0012FD2C

    &(x.d) = 0x0012FD2D



    карта ф памяти:

    0x0012FD24 - ...01 00 00 00 22 22 22 22 03 04 00 00 cc cc cc...



    вопрос:



    почему именно так? какая формула для вычисления оффсетов на члены структуры с участием коэффициента выравнивания (1,2,4,8 и 16)?



    в РТФМах для меня написано непонятливо. Очень жду по-децки простых и наивных объяснений. Спасибо!
     
  2. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    RTFMSDN: #pragma pack( [ show ] | [ push | pop ] [, identifier ] , n )


    Код (Text):
    1.  
    2. x.a: 0x0012FD24:  db  01 - выравнивается по границе байта;
    3. x.b: 0x0012FD28:  dd  0x22222222 - выравнивается по границе dword, поэтому перед ним добавляется 3 байта;
    4. x.c: 0x0012FD2C:  db  03 - выравнивается по границе байта;
    5. x.d: 0x0012FD2D:  db  04 - выравнивается по границе байта;
    6.  


    Вот почему sizeof(x) = 12 - это уже сложнее, т.к. про это RTFMSDN действительно не пишет.

    Вероятно, потому что структура находится в стэке :derisive:

    А стэк, как известно, всегда должен быть выровнен по границе не менее dword.
     
  3. ozzman

    ozzman New Member

    Публикаций:
    0
    Регистрация:
    22 янв 2004
    Сообщения:
    56
    sizeof(x) = 12, так как компилер по неизвестной мне причине не хочет выравнивать по 8, т.к.

    как в структуре нет типа переменой, с размером 8. Компилер использует выравнивание по умолчанию(4байта).



    К примеру:



    #pragma pack(8)



    struct x

    {

    char d;

    double f;

    };



    size x = 16 байт.
     
  4. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    ozzman >




    „Выравнивание члена (структуры) будет (происходить) по границе, которая кратна либо n, либо размеру члена, в зависимости от того, что меньше



    PS


    RTFMSDN рулит :)
     
  5. NeuronViking

    NeuronViking New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2004
    Сообщения:
    476
    Адрес:
    где-то в Сиднее
    насчет default packing value вообще сказка ;)

    для Вижуал 6.0 и до него - дефолтное значение 4 байта, для Вижуал 7.0 это 8 байт...

    так шта не всегда ртфм рулит ;) я счаз занят, вечером поковыряюсь... просто дело в том, что перечисленные S_T_A_S_ ом правила (из нового МСДНа) не всегда работают, и все что касается выравнивания мемберов из МСДНа я внимательно читал и перечитывал не один раз... но что-то тут не так, дома посмотрю пример который посылает в далекие края все эти правила...
     
  6. ozzman

    ozzman New Member

    Публикаций:
    0
    Регистрация:
    22 янв 2004
    Сообщения:
    56
    NeuronViking

    у меня временно стоит старый мсдн, и там написано про дефолтное выравнивание для старых версий VS. Думаю в новом мсдн можно найти для новых версий, соотв-но.
     
  7. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Я смотрю апрель 2003: ms-help://MS.MSDNQTR.2003APR.1033/vclang/html/_predir_pack.htm

    или вот

    и так как минимум с 2000 года



    Когда речь идёт о стэке, нужно учитывать особенности архитектуры, например если ESP не кратен 4 под NT, то система просто грохнет прогу при первой возможности.
     
  8. NeuronViking

    NeuronViking New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2004
    Сообщения:
    476
    Адрес:
    где-то в Сиднее
    со стеком вроде бы все понятно. если я не ошибаюсь то на IA-32 стековые данные всегда выровнены на естественную границу (2 или 4 байта)
     
  9. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Нет.

    Кратную 4
     
  10. NeuronViking

    NeuronViking New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2004
    Сообщения:
    476
    Адрес:
    где-то в Сиднее
    угу, в протектед моде
     
  11. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Дело не в этом.

    В ядре NT есть проверки, если ESP user-процесса не кратен 4, то система его завершает.
     
  12. NeuronViking

    NeuronViking New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2004
    Сообщения:
    476
    Адрес:
    где-то в Сиднее
    верно =)

    потому чьто ядро работает на ИА-32 в протектед модеи соответственно естественная граница выравнивания как следуюет из спецификации Intel IA-32 есьм 4 байта
     
  13. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    А user в каком режиме работает? %)



    Зацитируем IA-32 Intel® Architecture Software Developer’s

    Manual Volume 1: Basic Architecture







    Мастдае, например, не следит за стэком.



    NT, кстати, проверяетне только кратность ESP потока 4м, но и не выход за пределы, храняшиеся в TIB



    [fs:4];//StackBase - верхняя граница

    [fs:8];//StackLimit - нижняя граница