gcc, Выравнивание на 64-битных архитектурах
От: artem_korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 22.04.09 13:54
Оценка:
Столкнулся сегодня с одной проблемой. Есть структура данных, состоящая из нескольких полей — 64-битный float, потом 8 unsigned char и один Int32. Итого получается 20 байт (8 + 8*1 + 4). Под 32-битными системами sizeof равен 20 и всё работает нормально. А под 64-битным Linux'ом sizeof возвращает 24. Т.е. идёт выравнивание по границе 64 бит. Я пробовал добавлять в конец структуры директиву align:


struct ... {
    ...
} __attribute__ ((align(4)));


Не помогает. Всё равно sizeof возвращает 24. Проверял по отдельности — размеры каждого элемента правильные, т.е. 8 байт на Float64, по одному байту на каждый unsigned char и 4 байта на Int32.

Пока сделал маленький костыль, принудительно используя значение 20, вместо sizeof, но мне этот костыль не нравится, хочется сделать по-человечески. Что можно покурить для просветления?
С уважением, Artem Korneev.
gcc amd64
Re: gcc, Выравнивание на 64-битных архитектурах
От: ra88  
Дата: 22.04.09 14:09
Оценка: 31 (2) +1
Здравствуйте, artem_korneev, Вы писали:

_>Столкнулся сегодня с одной проблемой. Есть структура данных, состоящая из нескольких полей — 64-битный float, потом 8 unsigned char и один Int32. Итого получается 20 байт (8 + 8*1 + 4). Под 32-битными системами sizeof равен 20 и всё работает нормально. А под 64-битным Linux'ом sizeof возвращает 24. Т.е. идёт выравнивание по границе 64 бит. Я пробовал добавлять в конец структуры директиву align:



_>
struct ... {
_>    ...
_>} __attribute__ ((align(4)));


_>Не помогает. Всё равно sizeof возвращает 24. Проверял по отдельности — размеры каждого элемента правильные, т.е. 8 байт на Float64, по одному байту на каждый unsigned char и 4 байта на Int32.


_>Пока сделал маленький костыль, принудительно используя значение 20, вместо sizeof, но мне этот костыль не нравится, хочется сделать по-человечески. Что можно покурить для просветления?


Попробуй

#pragma pack(4)
struct TwojaStructura {
...
};
while true;
Re: gcc, Выравнивание на 64-битных архитектурах
От: Аноним  
Дата: 22.04.09 14:30
Оценка: 29 (1) +1
Здравствуйте, artem_korneev, Вы писали:

_>Столкнулся сегодня с одной проблемой. Есть структура данных, состоящая из нескольких полей — 64-битный float, потом 8 unsigned char и один Int32. Итого получается 20 байт (8 + 8*1 + 4). Под 32-битными системами sizeof равен 20 и всё работает нормально. А под 64-битным Linux'ом sizeof возвращает 24. Т.е. идёт выравнивание по границе 64 бит. Я пробовал добавлять в конец структуры директиву align:


aligned, а не align
http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html#Type-Attributes

а вообще вам надо:

struct my_packed_struct {
    ...
} __attribute__ ((__packed__));

my_packed_struct sss;
Re[2]: gcc, Выравнивание на 64-битных архитектурах
От: artem_korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 22.04.09 14:36
Оценка:
Здравствуйте, ra88, Вы писали:

R>Попробуй

R>#pragma pack(4)

Спасибо, помогло. Я удивлён, я думал, что #pragma pack это чисто майкрософтовское.

Интересно, а будет ли это работать под другими компиляторами? Мне-то нужно поддерживать код для gcc, icc, visual studio, и ещё каких-то там. Надо попробовать.
С уважением, Artem Korneev.
Re[3]: gcc, Выравнивание на 64-битных архитектурах
От: ra88  
Дата: 22.04.09 14:46
Оценка:
Здравствуйте, artem_korneev, Вы писали:

_>Здравствуйте, ra88, Вы писали:


R>>Попробуй

R>>#pragma pack(4)

_>Спасибо, помогло. Я удивлён, я думал, что #pragma pack это чисто майкрософтовское.


_>Интересно, а будет ли это работать под другими компиляторами? Мне-то нужно поддерживать код для gcc, icc, visual studio, и ещё каких-то там. Надо попробовать.


для "спасибо" кнопка есть

по gcc:
http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html#Structure_002dPacking-Pragmas

остальные не знаю...
while true;
Re: gcc, Выравнивание на 64-битных архитектурах
От: Erop Россия  
Дата: 22.04.09 19:07
Оценка:
Здравствуйте, artem_korneev, Вы писали:

_>
struct TEstStruct {
_>    ...
_>} __attribute__ ((align(4)));


_>Что можно покурить для просветления?


Прочти тут: http://www.rsdn.ru/Forum/message/1461439.aspx
Автор: Erop
Дата: 28.10.05
, тогда я смогу понятно объяснить дальше.

__attribute__ ((align(4))) задаст выравнивание, с которым потом будет размещаться структура TEstStruct, а на то, с какими выравниваниями будут размещаться её поля влияет pragma pack. В целом pragma pack присутствует в том или ином виде во всех известных мне компиляторах...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: gcc, Выравнивание на 64-битных архитектурах
От: Vain Россия google.ru
Дата: 22.04.09 19:47
Оценка:
Здравствуйте, artem_korneev, Вы писали:

_>
struct ... {
    ...
} __attribute__ ((align(4)));

_>Не помогает.
Не пробовали __attribute__ указывать перед структурой, а не после?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re: gcc, Выравнивание на 64-битных архитектурах
От: Pzz Россия https://github.com/alexpevzner
Дата: 22.04.09 23:45
Оценка:
Здравствуйте, artem_korneev, Вы писали:

_>Не помогает. Всё равно sizeof возвращает 24. Проверял по отдельности — размеры каждого элемента правильные, т.е. 8 байт на Float64, по одному байту на каждый unsigned char и 4 байта на Int32.


Если сделать массив из таких структур, то при размере структуры в 20 байт в каждой второй структуре float64 будет не выровнен. Чтобы этого избежать, gcc делает размер структуры кратным 8-и. Т.е., это выравнивание не между полями структуры, а после последнего поля.

Про #pragma pack вам уже рассказали, повторяться не буду Теоретически она obsoleted, лет уже наверное 10 как, но все не решаются выкинуть. У нее есть какой-то эквиавалент в виде атрибита, не помню, как его зовут.
Re[2]: gcc, Выравнивание на 64-битных архитектурах
От: artem_korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 25.04.09 18:29
Оценка:
Здравствуйте, Erop, Вы писали:

E>Прочти тут: http://www.rsdn.ru/Forum/message/1461439.aspx
Автор: Erop
Дата: 28.10.05
, тогда я смогу понятно объяснить дальше.


Почитал. Спасибо, интересно.

E>__attribute__ ((align(4))) задаст выравнивание, с которым потом будет размещаться структура TEstStruct, а на то, с какими выравниваниями будут размещаться её поля влияет pragma pack. В целом pragma pack присутствует в том или ином виде во всех известных мне компиляторах...


Я посмотрел на список поддерживаемых в проекте компиляторов, помедитировал над ним и решил переписать код сериализации так, чтобы он работал с данными отдельно, по элементам, а не со структурой. Не очень здорово в плане структуры кода, но в этом случае проблем с выравниванием нет. Использование директив компиляторов в моём случае чревато тем, что я могу наткнуться на компилятор, не поддерживающий эти директивы и тогда я получу кучу труднодиагностируемых глюков.
С уважением, Artem Korneev.
Re[3]: gcc, Выравнивание на 64-битных архитектурах
От: Erop Россия  
Дата: 25.04.09 20:28
Оценка:
Здравствуйте, artem_korneev, Вы писали:

_>Почитал. Спасибо, интересно.

Всегда рад.

_>...не поддерживающий эти директивы и тогда я получу кучу труднодиагностируемых глюков.

В принципе можно StaticAssert какой-нибудь написать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: gcc, Выравнивание на 64-битных архитектурах
От: _nn_ www.nemerleweb.com
Дата: 16.05.09 11:11
Оценка:
Здравствуйте, artem_korneev, Вы писали:

_>Здравствуйте, ra88, Вы писали:


R>>Попробуй

R>>#pragma pack(4)

_>Спасибо, помогло. Я удивлён, я думал, что #pragma pack это чисто майкрософтовское.


_>Интересно, а будет ли это работать под другими компиляторами? Мне-то нужно поддерживать код для gcc, icc, visual studio, и ещё каких-то там. Надо попробовать.


В принципе все поддерживают #pragma pack.
Если ищется универсальное решение, то можно сделать например как в библиотеке lwip:
ip.h
bpstruct.h
epstruct.h

#ifdef PACK_STRUCT_USE_INCLUDES
#  include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct ip_hdr {
  // ...
  // ...
  // ...
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
#  include "arch/epstruct.h"
#endif


Таким образом если компилятор поддерживает #pragma pack, pop можно воспользоваться этим, а если что-то другое как, скажем, __declspec(align) или __attribute__(aligned), то им.

#if VC
#define PACK_STRUCT_BEGIN __declspec(align(1)) 
#elif GCC
#define PACK_STRUCT_END __attribute__(aligned(1))
#elif OTHER_WITH_PRAGMA
#define PACK_STRUCT_USE_INCLUDES
#else
#error Not supported
#endif
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: gcc, Выравнивание на 64-битных архитектурах
От: artem_korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 18.05.09 08:03
Оценка:
Здравствуйте, _nn_, Вы писали:

__>В принципе все поддерживают #pragma pack.


Все — это кто? Действительно все, или только msvs, gcc и icc?

__>
__>#if VC
__>#elif GCC
__>#elif OTHER_WITH_PRAGMA
__>


Если через if/elif, то у меня список большой получится. Мне нужно чтобы всё это поддерживалось разными версиями компиляторов MSVS, PG, GCC, ICC, SC, IVA. Вполне может быть, что список будет пополняться. А уж тестирование всего этого добра под всеми поддерживаемыми версиями всех компиляторов на разных операционных системах — то ещё удовольствие. Поэтому я пока решил эту проблему на уровне языка C++, а не средствами препроцессора.
С уважением, Artem Korneev.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.