Няшная / Говнокод #18801 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  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 MiD, (Updated )

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

  • Че за хуйню ты несешь, какие невыравненные данные, че пошло по пизде, обкурился шоли и долбишься?
    Ответить
    • Был сделан массив структур struct test_node fooo[] = {
      {
      .name = ,
      .....
      },
      .name = ,
      .....
      {
      }};
      При обращении к полю элемента массива, выходит хуета.
      Ответить
      • А черепашка не выходит?
        Знаешь как со стороны это выглядит? "Пацаны, я тут бокрёнка кудрячил, а меня куздра будланула, как себя обезопасить?"
        http://ideone.com/ или выходить будут только черепашки и хуета
        http://ideone.com/zurpMq
        Ответить
      • 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.
          Ответить
            • Ну х.з., я бы для начала попробовал на чистом файлике вне проекта скомпилить что-нибудь в духе 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'
            Ответить
  • всё правильно. Передаешь структуры данных по сети - убедись что выравниваешь верно и что все поля имеют строго заданный размер.
    Ответить

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

Помни, guest, за тобой могут следить!

    А не использовать ли нам bbcode?


    8