beldmit: (Программизм)
[personal profile] beldmit
Наступил на грабли. gcc и g++ дают разный размер довольно развесистой структуры, используемой в сишной и плюсовой библиотеках.

Можно ли малой кровью их привести к единому знаменателю? С-шная библиотека не наша, плюсовая наша.

Вроде бы везде стоят флаги
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

Опцию -fpack-struct пробовал, не преуспел.

Update: разные опции сборки базовой и производной библиотек.

Date: 2019-07-11 04:47 pm (UTC)
vitus_wagner: My photo 2005 (Default)
From: [personal profile] vitus_wagner
А -S пробовал? В смысле, сгенерировать ассемблер и посчитать что получилось.

Впрочем я бы сначала попробовал вывести куда-нибудь в отладочный вывод offsetof всех полей и посмотреть где именно начинается расхождение.

Date: 2019-07-11 06:00 pm (UTC)
vladimir000: (Default)
From: [personal profile] vladimir000
Ну в принципе если кровь из носу надо, можно сделать структуру, в которй челенами будут юнионы-битовые поля...

Кажется, такая порнография еще не запрещена и результат нужный выдаст...

Date: 2019-07-12 05:01 am (UTC)
vitus_wagner: My photo 2005 (Default)
From: [personal profile] vitus_wagner
Поэтому нужно докопаться до сути. Вплоть до чтения исходников компилятора. Вот после того, как будешь понимать почему именно так произошло, и почему так не проихсодит у других, и все спокойно передают из C++-ного кода структуры в C-шные библиотеки и обратно, а в этом случае не получается, тогда получится сделать надежное (ну в рамках текущего поколения компиляторов) решение.

Date: 2019-07-11 05:13 pm (UTC)
From: [personal profile] malobukov
А разве можно рассчитывать на то, что размер структуры будет одинаковым? Вроде компилятору разрешено по желанию размещать поля структуры как ему захочется, например, чтобы оптимизировать время доступа к элементам структуры на процессорах, где выравнивание влияет.

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

Date: 2019-07-11 05:33 pm (UTC)
vladimir000: (Default)
From: [personal profile] vladimir000
Именно так. Теоретически что-то можно придумать, но жить это будет - самый максимум до перекомпиляции на омпьютере с другой архитектурой или размером данных.

Date: 2019-07-11 08:07 pm (UTC)
nasse: (Default)
From: [personal profile] nasse
Хм. Тест.

Date: 2019-07-11 07:02 pm (UTC)
elglin: (Default)
From: [personal profile] elglin
Я уже давно не сварщик, но придумывается только восход солнца руками в духе:
char pseudostruct[16]; /* int, char[4], double */

int get_a(char* p){ return *((int*)p); }
void set_a(char* p, int v){ *((int*)p) = v; }
char* get_b(char* p){ return p + 4; }
void set_b(char* p, char* v){ strncpy(p, v, 4); }
double get_c(char* p){ return *((double*)(p + 8)); }
void set_c(char* p, double v){ *((double*)(p + 8)) = v; }

Обвешать inline по вкусу. Но это уже подозрительно напоминает попытку ASM-вставки без ASM-вставки и той самой ручной оптимизации, которая очень эффективно замедляет код.

Date: 2019-07-11 09:49 pm (UTC)
From: [personal profile] being_no_one
Опасный фокус даже в этом примере. Если бы размер int был 8 байт, то аналогично реализованный get_c содержал бы UB, ибо *((double*)(p + 12)) нарушает требования к выравниванию для double; при попытке поступить так с действительно большой структурой шанс наступания на эти грабли опасно высок.
Edited Date: 2019-07-11 09:51 pm (UTC)

Date: 2019-07-12 06:51 am (UTC)
elglin: (Default)
From: [personal profile] elglin
Без фигни опасный, а еще int разный на разных архитектурах. Тут для стабильности надо структуру делать кратной 64 битам (то есть не char[], а int64_t[]), молиться, что этот кусок кода выкинут до перехода на 128-битовое слово, и все равно при такой указательной магии есть шанс отстрелить себе ногу.
Мой научник 20 лет назад поминал идею о том, что иногда стоит сделать конский malloc(), а дальше внутри него раскладывать то, что тебе нужно, по сути, реализуя свой маленький менеджер памяти. Это вот ровно то же самое; подозреваю, это до сих пор верно в ситуациях, когда у тебя 64К памяти, и ты реально лучше любого компилятора знаешь, что где как должно лежать.

Date: 2019-07-12 04:57 am (UTC)
vitus_wagner: My photo 2005 (Default)
From: [personal profile] vitus_wagner
Речь идет о том, что один и тот же компилятор, компилируя один и тот же код на одной и той же архитектуре разными языковыми фронтэндами, должен бы понимать структуру одинаково.

Более того, вообще-то и разные компиляторы на одной архитектуре - тоже.

Потому что в системных ABI разных операционных систем ДО ХРЕНА структур, передаваемых как параметры и как-то это работает.

Date: 2019-07-11 09:34 pm (UTC)
From: [personal profile] being_no_one
Первое, что хочется проверить: а нет ли в коде этой развесистой структуры пар ifdef-endif?
Если нет, то я бы всё-таки вначале понял, где именно возникает расхождение - тупо получил от C-библиотеки структуру с известными полями и посмотрел в памяти. Потому что понятно что стандарт двоичной совместимости не гарантирует, но практически расхождение странное, я бы сомневался в точности диагноза. Опять же, если понять какой тип вызывает проблемы, может получиться обойтись малой кровью.

Date: 2019-07-12 05:17 am (UTC)
vitus_wagner: My photo 2005 (Default)
From: [personal profile] vitus_wagner
Еще интересно что за gcc. Сейчас их в дикой природе существует от 4.3 до 9.
Кстати, интересно, в Герцогстве Горностайском (в смысле Ubuntu eoan ermine) уже 9 или еще не втащили. Ну в понедельник на работу выйду, посмотрю.

Date: 2019-07-12 06:50 am (UTC)
vitus_wagner: My photo 2005 (Default)
From: [personal profile] vitus_wagner
"Как минимум начиная с 6-й" это очень ограниченные представления о "везде".
6-й Редхат и 11 SLES пока вполне актуальны. Кстати, не дождался понедельника и скачал
http://archive.ubuntu.com/ubuntu/dists/eoan/binary-amd64/Packages.gz.
Там уже 9.1.

Date: 2019-07-12 11:29 am (UTC)
From: [personal profile] cross_join
Си++ и Си-структуры суть разные сущности (в Си++ структура тот же класс, она хранит информацию о видимости членов, может содержать vtable и т.д.). Поэтому концептуально правильно написать функции сериализации и десереализации.

Date: 2019-07-12 02:56 pm (UTC)
yurikhan: (Default)
From: [personal profile] yurikhan
В C++, однако, есть понятие POD (Plain Old Data), для которых гарантируется довольно много вещей, делающих их совместимыми с сишными структурами.

Date: 2019-07-12 03:50 pm (UTC)
From: [personal profile] cross_join
POD, POJO, POCO и т.д. есть практически везде, где есть ООП (классы и объекты), и стандартный способ обмена ими - упаковка и распаковка.
В Си++ у стрктуры-класса будет дефолтные конструктор и деструктор, создавать их надо через new (или на стеке). В Си у структуры нет никаких деструкторов, создавать их надо через malloc.

Date: 2019-07-12 07:08 pm (UTC)
yurikhan: (Default)
From: [personal profile] yurikhan
В C++ официально допустимый способ обмена POD’ами — memcpy из байтового буфера. На практике, никаких носодемонов не вылетает и при reinterpret_cast’е указателя на байтовый буфер в указатель на POD-структуру, если при этом не нарушаются требования выравнивания.

Date: 2019-07-15 08:03 am (UTC)
From: [personal profile] cross_join
В Си++ или в связке с Си?
Это часть стандарта?

Date: 2019-07-15 12:31 pm (UTC)
yurikhan: (Default)
From: [personal profile] yurikhan

Что значит «в связке с Си»? Стандарты C и C++ не специфицируют точное представление типов, оставляя это на откуп реализации. Реализации же в большинстве своём делают в соответствии с ABI платформы. Раскладывать плюсовую структуру совместимо с аналогичной сишной — в большинстве случаев достаточно экономично по памяти и быстродействию и выгодно для interoperability.

Плюсовые структуры, удовлетворяющие требованиям на plain old data (C++11 [class]#6–10), будучи побайтово скопированы в байтовый буфер, а затем обратно в память, занятую экземпляром той же самой структуры — остаются валидными объектами, почленно равными исходным (C++11 [basic.types]#2). Указатель на POD-структуру численно равен указателю на её первое поле (C++11 [class.mem]#17–20). Да, здесь нет явного разрешения копировать полученный извне байтовый массив в underlying bytes структуры и рассчитывать на правильную интерпретацию; это, на самом деле, к ABI.

Profile

beldmit: (Default)
Dmitry Belyavskiy

December 2025

S M T W T F S
 123456
78910111213
14151617181920
2122 2324252627
28293031   

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Dec. 28th, 2025 01:02 am
Powered by Dreamwidth Studios