1. Си / Говнокод #18801

    −3

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    enum test_result {
        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;
    }

    О духи говнакода наставьте агнца вашего на путь истинный. Написал сие я, запустил и всё пошло по п*изде, по причине невыравненых данных. #pragma pack не помог. Помогло лишь изменение типа enum test_result на uint8_t. Подскажите, дабы не наступать на подобные грабли болей, как кто себя проверяет при работе со структурами?

    Запостил: MiD, 02 Октября 2015

    Комментарии (21) RSS

    • Че за хуйню ты несешь, какие невыравненные данные, че пошло по пизде, обкурился шоли и долбишься?
      Ответить
      • Был сделан массив структур struct test_node fooo[] = {
        {
        .name = ,
        .....
        },
        .name = ,
        .....
        {
        }};
        При обращении к полю элемента массива, выходит хуета.
        Ответить
        • Сам ты хуета
          Ответить
        • А черепашка не выходит?
          Знаешь как со стороны это выглядит? "Пацаны, я тут бокрёнка кудрячил, а меня куздра будланула, как себя обезопасить?"
          http://ideone.com/ или выходить будут только черепашки и хуета
          http://ideone.com/zurpMq
          Ответить
      • это байтоебство называется
        тут например об этом сказано http://habrahabr.ru/post/142662/
        Ответить
        • enum __attribute__((aligned(4), packed)) test_result {
          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.
        Ответить
        • А если алгоритм подбора хранилища для енумов детерминистический, то на какие грабли мог наступить MiD?
          Ответить
          • Надо больше контекста. Что именно он делал с массивами этих структур. Писал на диск/в сокет. Или просто передавал между модулями. Или всё распидорасило на каком-нибудь ARM'е, придирчивом к alignment'у. Или что-то ещё.
            Ответить
            • >Или всё распидорасило на каком-нибудь ARM'е
              Ответить
          • тут про грабли можно поподробнее?
            Ответить
    • Да, слошил. Надо было поконкретнее написать. Писалось для stm32l151. В конфигурационном модуле уже упамянутый массив структу. Один из полей элемента массива enum. Далее в другом модуле пробегался по массиву, сопоставлял имя *name с полученым из вне и если было совпадение выполнялся обработчик measurement_test_handler, результат записывался в meas_result и init_result. Проблема была в том что при выполнении sizeof() для enum'a получал 1. В итоге выходила что 2 енума он хиракнул в 2 байта и как следствие произошел сдвиг.
      Ответить
      • Ну а левый pragma pack не пролез случаем откуда-нибудь? Просто компиляторы по-умолчанию стараются всё правильно выравнивать... Даже если sizeof(enum) был 1, он должен был 2 байта padding'а воткнуть в конце структуры, чтобы всё красиво легло.
        Ответить
        • про левый pragma pack не знаю, т.к. "сажаю новое дерево уже в очень дремучем лесу"
          Ответить
          • А какой компилятор в тулчейне? gcc? Версия?

            Если gcc - глянь, нет ли случаем в параметрах компилятора какого-нибудь говна типа -fpack-struct.
            Ответить
            • arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.9.3
              Ответить
              • Ну х.з., я бы для начала попробовал на чистом файлике вне проекта скомпилить что-нибудь в духе 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'
              Ответить
    • всё правильно. Передаешь структуры данных по сети - убедись что выравниваешь верно и что все поля имеют строго заданный размер.
      Ответить

    Добавить комментарий