LINUX.ORG.RU

«неровное» выравнивание структур в gcc 4.0.1


0

0

Есть две структуры:

typedef struct READ_ENERGY_EXT
{
	unsigned char array_num;
	unsigned char month_num;
	unsigned char tarif_num;
	unsigned char mask;
	unsigned char format;

	double Ap;
	double Am;
	double Rp;
	double Rm;

	double R1;
	double R2;
	double R3;
	double R4;
} ENERGY_REG;


typedef struct READ_FLASH_POWER
{
	unsigned char power_type;
	unsigned char phase_num;

	double P[4];
	double Q[4];
	double S[4];
} FLASH_POWER;

при компиляции gcc 4.0.1
sizeof(ENERGY_REG) - 72
sizeof(FLASH_POWER) -100

при копмиляции C++ Builder

sizeof(ENERGY_REG) - 72
sizeof(FLASH_POWER) -104

насколько я знаю стукрура выравнивается что бы итоговый
размер был кратный наибольшему типу в структуре, то есть
в случае второй структуры кратным 8(double), как это делает Builder,
почему же тогда gcc делает 100 байт. При чем, причем всякие там 
#pragma pack(push, 8) и __attribute__((aligned(8))) дело не меняют,
все равно 100 байт. Менять опцию оптимизации(-O) пробовал, тоже самое.
Необходимо перебавать структуры через сокеты с lin сервера на win 
клиент. Выравнивать по байту неохото ибо потеряю в производительности,
и конвертировать стуктуру в строку тоже, т.к. структур много, да и не
использовать удобную функцию сокетного send`a тоже 

попробуй __attribute__((packed)) при чем делай typedef отдельно:

struct Foo { ... } __attribute__((packed));

typedef Foo foo_t;

no1sm ★★
()
Ответ на: комментарий от no1sm

> попробуй __attribute__((packed)) ...

не то... , получиться, если б я убрал выравнивание, мало того, что это придётся делать в обоих средах, ещё и упадёт произвадительность, в принципе временно проблему я решил путем выравнивания структуры READ_FLASH_POWER по 4 байтам в Builder`е, но просто интересно почему гнутый копмилятор выравнивает по 4 байта, когда должет по 8, да ещё не слушает, меняющие это, директивы

yuko
() автор топика

> насколько я знаю стукрура выравнивается что бы итоговый размер был кратный наибольшему типу в структуре

а насколько я знаю, компилятор может выравнивать как хочет :) Грубо говоря, он может вообще поменять местами все поля структуры кроме первого. В стандарте есть только одно требование - адрес первого поля структуры долен совпадать с адресом самой структуры.

а писать код, зависящий от выравнивания - IMHO плохой стиль.

anonymous
()
Ответ на: комментарий от anonymous

>а насколько я знаю, компилятор может выравнивать как хочет :)

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

>а писать код, зависящий от выравнивания - IMHO плохой стиль.

это понятно, но так меньше гемора с транспортировкой данных через сокеты.

>-malign-double

думаю не подойдёт, т.к. распространяется на весь код, а необходимо выровнять часть структур, кто му же получится оптимизация под пентиум, а целевая система будет Geode. И ещё настораживает:

> Предупреждение: Если вы используете опцию '-malign-double', структуры, содержащие выше перечисленные типы будут выравниваться не так, как в опубликованных спецификациях прикладного двоичного интерфейса для 386.

yuko
() автор топика
Ответ на: комментарий от yuko

>>а писать код, зависящий от выравнивания - IMHO плохой стиль.

>это понятно, но так меньше гемора с транспортировкой данных через сокеты.

Это о-малое от геморра, который поимеет программер, решивший в данном проекте поменять компилятор / платформу.

Kpoxman ★★
()
Ответ на: комментарий от Kpoxman

> насколько я знаю стукрура выравнивается что бы итоговый размер был кратный наибольшему типу в структуре, то есть в случае второй структуры кратным 8(double), как это делает Builder, почему же тогда gcc делает 100 байт.

касательно размера - это union

выравнивание относится не к размерам объектов а к адресам (виртуальным) по которым они расположены

проверил (хотя gcc 3.4.3) - без выравнивания 100 с выравниванием 104 - всё как надо

Mr_Nobody
()
Ответ на: комментарий от Kpoxman

>Это о-малое от геморра, который поимеет программер, решивший в данном проекте поменять компилятор / платформу.

это понятно :-), потом всяко придеться по-человечески переделывать (сетевой обмен), просто сейчас нужно бысто сделать "что б работало"

yuko
() автор топика
Ответ на: комментарий от Mr_Nobody

>проверил (хотя gcc 3.4.3) - без выравнивания 100 с выравниванием 104 - всё как надо

у меня без выравнивания 98 (собственно, сумма всех переменных структуры)

yuko
() автор топика

#pragma pack(0) точно не помогает?

theserg ★★★
()
Ответ на: комментарий от yuko

>это понятно, но так меньше гемора с транспортировкой данных через сокеты.

сериализация и десериализация мало того что не сильно подорвёт производительность при передаче через сетевые сокеты, она ещё даст возможность менять компиляторы, платформу и язык программирования (например, сервер на java). Не хотел бы я поддерживать код зависящий от версии gcc (а завтра программу постявят на итаниум, чего будешь делать ?). Как обычно программисты ищут проблемы и потом мужественно их решают.

vtVitus ★★★★★
()
Ответ на: комментарий от Kpoxman

> > это понятно, но так меньше гемора с транспортировкой данных через сокеты.
> Это о-малое от геморра, который поимеет программер, решивший в данном проекте поменять компилятор / платформу.

Опять? Вы где этого наслушались? На лекциях? Блин. Структуры при IO использовать можно и в инекоторых случаях необходимо. Примеров куча -- IP, X11, бинарные форматы (tar, elf, bmp, ...).

http://www.linux.org.ru/view-message.jsp?msgid=1128108

logIN
()
Ответ на: комментарий от vtVitus

> сериализация и десериализация мало того что не сильно подорвёт производительность

Да ну!? А ну-ка ну-ка, заверни ка протоколы низкого уровня в XML и посмотрим как у тебя не подорвётся производительность.

> код зависящий от версии gcc

Код зависит от gcc у тех, кто писать не умеет. Еще раз смотри на примеры правильного использования структур при IO.

> например, сервер на java

Всё понятно. Тебя как огня бояться надо.

logIN
()
Ответ на: комментарий от logIN

> Код зависит от gcc у тех, кто писать не умеет. Еще раз смотри на примеры правильного использования структур при IO.

Я утверждаю, что не существует правильного способа без сериализации записывать структуры в байтовый поток (файл или сокет) на языке С\С++. Правильный означает - чтобы код без изменений компилировался и работал под произвольной платформой, где например упакованные структуры невозможны в принципе, или где другой поряок байтов в целых числах.

Если вы с этим не согласны, приведите пример кода (конкертный текст или ссылку), где структура напрямую пишется\читается.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

> Я утверждаю

Да сколько влезет.

> приведите пример кода (конкертный текст или ссылку),

Не буду себя утруждать, приведу код в котором недавно сам копался:

xorg-server-1.1.1/hw/kdrive/linux/evdev.c

static void
EvdevRead (int evdevPort, void *closure)
{
KdMouseInfo *mi = closure;
Kevdev *ke = mi->driver;
int i;
struct input_event events[NUM_EVENTS];
int n;

n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event));

logIN
()
Ответ на: комментарий от logIN

2logIN:

>> сериализация и десериализация мало того что не сильно подорвёт производительность

> Да ну!? А ну-ка ну-ка, заверни ка протоколы низкого уровня в XML ...

Да кто про сериализацию в XML говорит, кроме тебя? Ты хоть немного про эту самую сериализацию, кроме как из лекций, знаешь?

2All:

Выше logIN верную ссылку дал. Уж там _все_ обсудили! Сходите, почитайте и решайте сами, кто прав.

Die-Hard ★★★★★
()
Ответ на: комментарий от logIN

logIN (21.10.2006 2:27:25):

Ну, именно за такое и нужно немедленно лечить методом профессора Луговского :-)

Вот именно из-за таких решений моего (старшего) коллеги я недавно два месяца занимался заполуночным сэксом с витееватым конвертором индейцев.

Разумеется, ИНОГДА такое полезно (как, наверное, в приведенном примере). Но это СЛОЖНО и, КАК ПРАВИЛО, оно ВРЕДНО.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Но это СЛОЖНО и, КАК ПРАВИЛО, оно ВРЕДНО.

Бла-бла-бла. Ты приводишь свои утверждения ни на что не опираясь. Кто сказал что это сложно и вредно?! Опыт показывает, что это проще и быстрее чем сериализация. Где тут вред? Вред от тех, кто инструментом пользоваться не умеет.

В прошлом треде я целый день распинался перед вами, теоретиками, ссылки давал, цитаты. Теперь вот по второму кругу. Да вы не пробиваемы. Ворчите себе под нос как психи: "структуры, нельзя, нельзя, структуры, нельзя, нельзя, нельзя". Где вы такое заучили?


"Еще моя гипотеза: мозг Шарика в собачьем периоде его жизни накопил бездну понятий. Все слова, которыми он начал оперировать в первую очередь, - уличные слова, он их слышал и затаил в мозгу. Теперь, проходя по улице, я с тайным ужасом смотрю на встречных псов. Бог их знает, что у них таится в мозгах." (c) Собачье сердце

logIN
()
Ответ на: комментарий от logIN

> ... перед вами, теоретиками, ...

:-)

Я-то, как раз, в этом смысле практик, давно вышедший из пыонэрского возраста. Поэтому и пытаюсь нейтрализовать вредное влияние на неокрепшие умы подобных тебе экстремистов;)

:-)

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Поэтому и пытаюсь нейтрализовать

Лучше ничего не нейтрализовывать, а говорить объективно сразу.

Меня всегда удивляет вот такой диалог:

- Я хочу послать через сокет струк..
- НЕЛЬЗЯ, МАТЬ ТВОЮ! НЕЛЬЗЯ! АПСТЕНУ, УБЛЮДОК!

^^ это дезинформация.

logIN
()
Ответ на: комментарий от logIN

> Опыт показывает, что это проще и быстрее чем сериализация.

А еще опыт показывает, что при сборках разными компиляторами в таких ситуациях возникают ТАКИЕ жопы, что проще удавиться. Я однажды разгребал такую ситуацию - и закончилось все сериализацией.

no-dashi ★★★★★
()
Ответ на: комментарий от no-dashi

какая горячая дискуссия развернулась :-), я считаю, что сериализация правильней, чем ручное выравнивание структур, но как я говорил уже, нужно было, что б "сейчас работало", в дальнейшем придёться переделывать т.к. платформа в дальнейшем будет другая... да и вообще, разная. Интересно собственно было, почему gcc не хочет выравнивать вторую стукруту по 8 байтам, а только либо по 4(как я понял по умолчанию), либо меньше(по 1 работает), при чем не помогает ни одна из директив (#pragma pack(push, 8) , #pragma pack(8) , __attribute__((aligned(8)))

yuko
() автор топика
Ответ на: комментарий от Die-Hard

> Выше logIN верную ссылку дал. Уж там _все_ обсудили! Сходите, почитайте и решайте сами, кто прав.

Содержательная ссылка, особенно концовка. :)

amm
()
Ответ на: комментарий от yuko

Интересно, а builder про offsetof(FLASH_POWER, P) что говорит?

amm
()
Ответ на: комментарий от logIN

> В прошлом треде я целый день распинался перед вами, теоретиками, ссылки давал, цитаты.

Твои примеры (xorg) и есть примеры сериализации, в _реализации_ которой для задания отступов полей применяются структуры.

> Теперь вот по второму кругу. Да вы не пробиваемы. Ворчите себе под нос как психи: "структуры, нельзя, нельзя, структуры, нельзя, нельзя, нельзя". Где вы такое заучили?

Тебе сказали, что можно, а ты остановиться не можешь.

amm
()
Ответ на: комментарий от logIN

Вы согласны, что переносимым образом невозможно сделать
write (fd, &a_struct, buff_len); // на 1 хосте
read (fd, &a_struct, buff_len); // на 2 хосте
use(a_struct.some_field);

как структуру не опиши?

sf ★★★
()
Ответ на: комментарий от sf

> Вы согласны, что переносимым образом невозможно сделать

Согласен, конечно. Однако, если структура кратна машинному слову или за'pad'ина до кратности, то структура это или нет не играет никакой роли. Потому как надо всегда договариваться об endianess -- так делают в любом бинарном протоколе. Так делают в любом текстовом протоколе, который wchar_t. Так делают в любом socket-aware приложении (htonX). Посылай всё в network byte order и не знай проблем.

logIN
()
Ответ на: комментарий от sf

> Без каких либо ограничений на размер полей?

Когда передаешь структуру -- ограничений море. И размеры полей, и разное представление отрицательных чисел, и разное представление дробных чисел, и т.д. и т.п. Твоя задача спроектировать протокол так, чтобы "вписаться" в эти ограничения или их обойти (выравнивание, в крайнем случае упаковка, договоренности об endianess, об представлении числа, ...). Но всё это решаемо и является стандартными проблемами при работе на низком уровне. Не хочешь думать об этих проблемах? Тогда не нужно выбирать С в качестве языка разработки.

logIN
()
Ответ на: комментарий от sf

> Мне просто кажется, что ваше решение ограничено 32-разрядными машинами.

Прочитай прошлый тред, ссылку на который я давал выше. Там и про машины и про разрядности.

logIN
()
Ответ на: комментарий от logIN

Ну если на следование байт забить.

ISO/IEC 9899:TC2 6.7.2.1: пункт 10.

После прочтения впечатление такое: чтобы не было неоднозначностей в разбросе или езде полей, Все поля нужно делать размером в 1 addressable storage unit(ASU). Если хочется передавать флажки - уже нужно возиться с запихиванием битов в машинное слово (это уже сериализация :]). Если ASU - одинаковые на машинах - вроде бы проблем нет, а если разные, то геморроя получается больше, чем самому паковать биты в ячейки, равные НОК (ASU всех target машин).

Не так много и попередаешь.

sf ★★★
()
Ответ на: комментарий от logIN

глубокоуважаемый logIN, это Ваше

>спроектировать протокол так, чтобы "вписаться" в эти ограничения ... договоренности об endianess, об представлении числа, ...

как раз и называется сериализацией :)

"Сериализация (в программировании) — способ перевода какой-либо структуры данных в последовательность битов." (q) Википедия

anonymous
()
Ответ на: комментарий от anonymous

anonymous (*) (24.10.2006 2:09:48):

> как раз и называется сериализацией :)

ИМХО не следует переводить дискуссию в чисто терминологическое русло.

logIN утверждает, что для сериализации структур в битовый (ок, байтовый) поток логичнее пользоваться операциями чтения/записи над структурами, а потом их перетасовывать.

Оппоненты (и я, в том числе) утвеждают, что разумнее для этого читать/писать данные неструктурированно и потом распихивать их по полям соответствующей структуры.

ИМХО второй подход, ОЧЕВИДНО, более логичен и прост (хотя бы в силу того, что на разных архитектурах даже упакованные структуры будут иметь различный размер). logIN настаивает (как я понимаю) на первом подходе.

Что ж, гланды тоже можно вырезать автогеном вместо скальпеля, и не обязательно через рот...

Die-Hard ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.