Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
О духи говнакода наставьте агнца вашего на путь истинный. Написал сие я, запустил и всё пошло по п*изде, по причине невыравненых данных. #pragma pack не помог. Помогло лишь изменение типа enum test_result на uint8_t. Подскажите, дабы не наступать на подобные грабли болей, как кто себя проверяет при работе со структурами?
А черепашка не выходит?
Знаешь как со стороны это выглядит? "Пацаны, я тут бокрёнка кудрячил, а меня куздра будланула, как себя обезопасить?" http://ideone.com/ или выходить будут только черепашки и хуета http://ideone.com/zurpMq
Маловато контекста, но у меня есть подозрение, что дело не в выравнивании, а в размере енумов. Компилятор в разных модулях может выделять под енум разное количество байтиков в зависимости от режима оптимизации, графика приливов на Венере и розы ветров на Юпитере.
Когда енум используется per se, до этого никому нет никакого дела, ведь всё работает же. А когда енум завёрнут в сложный тип (массив, структура), то все последующие данные могут съехать, если компилятор под него выделит другой базовый тип.
Надёжнее всего будет внутри структур и массивов использовать числовые типы данных с гарантированным размером (uint8_t, uint16_t, uint32_t etc).
> Компилятор в разных модулях может выделять под енум разное количество байтиков в зависимости от режима оптимизации, графика приливов на Венере и розы ветров на Юпитере.
Нет. Компилятор определяет underlying тип для енума только на основе значений, которые может принимать enum.
Надо больше контекста. Что именно он делал с массивами этих структур. Писал на диск/в сокет. Или просто передавал между модулями. Или всё распидорасило на каком-нибудь ARM'е, придирчивом к alignment'у. Или что-то ещё.
Да, слошил. Надо было поконкретнее написать. Писалось для stm32l151. В конфигурационном модуле уже упамянутый массив структу. Один из полей элемента массива enum. Далее в другом модуле пробегался по массиву, сопоставлял имя *name с полученым из вне и если было совпадение выполнялся обработчик measurement_test_handler, результат записывался в meas_result и init_result. Проблема была в том что при выполнении sizeof() для enum'a получал 1. В итоге выходила что 2 енума он хиракнул в 2 байта и как следствие произошел сдвиг.
Ну а левый pragma pack не пролез случаем откуда-нибудь? Просто компиляторы по-умолчанию стараются всё правильно выравнивать... Даже если sizeof(enum) был 1, он должен был 2 байта padding'а воткнуть в конце структуры, чтобы всё красиво легло.
Ну х.з., я бы для начала попробовал на чистом файлике вне проекта скомпилить что-нибудь в духе struct foo { int x; char y; }, и посмотреть её размер. Для 32-битного проца он должен быть 8. Если нет - компилятор изначально кривой.
Потом, если во внешнем файле получается 8, я попробовал бы скомпилить такую структуру в файле внутри проекта, но не подключая к нему хедеров. Если получится 5 - значит косяк в опциях (-fpack-struct?) или в насильно заинклуженных через опции файлах.
Если и так 8 - то начал бы цеплять хедеры, которые были в тех модулях. Делением пополам нашёл бы из какого именно вылез косяк...
если я правильно смотрю, то нету. Всё что из Сфлагов:
'-O2',
'-Werror',
'-Wall',
'-fmessage-length=0',
'-fsigned-char',
'-mthumb',
'-mcpu=cortex-m3',
'-ffunction-sections',
'-fdata-sections',
'-std=c11',
'-fno-common',
'-Wno-format',
'-g',
'-pipe',
'-Dprintf=iprintf',
'-Dsprintf=siprintf',
'-Dvsprintf=vsiprintf'
{
.name = ,
.....
},
.name = ,
.....
{
}};
При обращении к полю элемента массива, выходит хуета.
Знаешь как со стороны это выглядит? "Пацаны, я тут бокрёнка кудрячил, а меня куздра будланула, как себя обезопасить?"
http://ideone.com/ или выходить будут только черепашки и хуета
http://ideone.com/zurpMq
тут например об этом сказано http://habrahabr.ru/post/142662/
TEST_FAILED = -1,
TEST_SKIPPED,
TEST_OK
}
struct test_node {
const char *name;
const char *descr;
enum test_result (*measurement_test_handler)(void* params);
void *params;
enum test_result meas_result;
enum test_result init_result;
}
Это исправило ситуацию.
Когда енум используется per se, до этого никому нет никакого дела, ведь всё работает же. А когда енум завёрнут в сложный тип (массив, структура), то все последующие данные могут съехать, если компилятор под него выделит другой базовый тип.
Надёжнее всего будет внутри структур и массивов использовать числовые типы данных с гарантированным размером (uint8_t, uint16_t, uint32_t etc).
Нет. Компилятор определяет underlying тип для енума только на основе значений, которые может принимать enum.
Если gcc - глянь, нет ли случаем в параметрах компилятора какого-нибудь говна типа -fpack-struct.
Потом, если во внешнем файле получается 8, я попробовал бы скомпилить такую структуру в файле внутри проекта, но не подключая к нему хедеров. Если получится 5 - значит косяк в опциях (-fpack-struct?) или в насильно заинклуженных через опции файлах.
Если и так 8 - то начал бы цеплять хедеры, которые были в тех модулях. Делением пополам нашёл бы из какого именно вылез косяк...
Как-то так.
'-O2',
'-Werror',
'-Wall',
'-fmessage-length=0',
'-fsigned-char',
'-mthumb',
'-mcpu=cortex-m3',
'-ffunction-sections',
'-fdata-sections',
'-std=c11',
'-fno-common',
'-Wno-format',
'-g',
'-pipe',
'-Dprintf=iprintf',
'-Dsprintf=siprintf',
'-Dvsprintf=vsiprintf'