Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

__attribute__ ((__packed__)), GCC > 4.4.0
http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=14781
Страница 1 от 1

Автор:  [ Пет Сеп 16, 2016 4:34 pm ]
Заглавие:  __attribute__ ((__packed__)), GCC > 4.4.0

Имам следният код:

Код:
#include <stdint.h>

#define DUMB_STATIC_ASSERT(test) typedef char assertion_on_mystruct[( !!(test) )*2-1 ]
#define ATTR_PACKED __attribute__ ((__packed__))
//#define ATTR_PACKED __attribute__ ((packed))

typedef union ATTR_PACKED tagMSG {
    struct ATTR_PACKED {
        uint32_t    ID;
        uint8_t     MSGTYPE;
        uint8_t     LEN;
        uint8_t     DATA[8];
    };
    struct ATTR_PACKED {
        uint8_t     ID_B0;
        uint8_t     ID_B1;
        uint8_t     ID_B2;
        uint8_t     ID_B3;
    };
    uint8_t     BUF[14];
} MSG;
DUMB_STATIC_ASSERT( sizeof(MSG) == 14 );

typedef struct ATTR_PACKED tagHID {
    //#pragma pack(1)
    uint8_t     cmd;
    uint8_t     nmsgs;
    uint32_t    stamp;
    uint8_t     TEC;
    uint8_t     REC;
    MSG  msg[4];
    //#pragma pack()
} HID;
DUMB_STATIC_ASSERT( sizeof(HID) == 64 );



При GCC 4.4.0, 32-bit MinGW, Win7 64-bit, sizeof е както следва:
sizeof(MSG)=14
sizeof(HID)=64

При GCC 4.9.1, 64-bit MinGW, Win7 64-bit и GCC 5.3.0, 32-bit MinGW, Win7 64-bit, съответно е:
sizeof(MSG)=14
sizeof(HID)=66

Поради каква причина GCC 4.9.x и 5.3.x не възприемат __attribute__ ((__packed__)) ??

Автор:  woody [ Пет Сеп 16, 2016 6:26 pm ]
Заглавие:  Re: __attribute__ ((__packed__)), GCC > 4.4.0

Защо е с подчертавки самото "packed" ? И защо правилната версия е закоментирана?

Автор:  [ Пет Сеп 16, 2016 7:03 pm ]
Заглавие:  Re: __attribute__ ((__packed__)), GCC > 4.4.0

woody написа:
Защо е с подчертавки самото "packed" ? И защо правилната версия е закоментирана?

И двете са "правилни", но не работят :-)
Засега зареших проблема като декларирах stamp като Reg32:
Код:
typedef union ATTR_PACKED tagReg32 {
    struct ATTR_PACKED {
        uint8_t   b0;   // LSB
        uint8_t   b1;
        uint8_t   b2;
        uint8_t   b3;   // MSB
    };
    struct ATTR_PACKED {
        uint16_t w0;// LSB
        uint16_t w1;// MSB
    };
    uint32_t dw;
} Reg32;

typedef struct ATTR_PACKED tagHID {
    //#pragma pack(1)
    uint8_t     cmd;
    uint8_t     nmsgs;
    Reg32     stamp;
    uint8_t     TEC;
    uint8_t     REC;
    MSG  msg[4];
    //#pragma pack()
} HID;


Сега sizeof(HID)=64, ама понеже трябва в много apps да променям структурата, ми
се ще да намеря причината защот новите GCC версии правят нещо различно от
примерно GCC 4.4.0

Автор:  ДедоБоре [ Пет Сеп 16, 2016 7:34 pm ]
Заглавие:  Re: __attribute__ ((__packed__)), GCC > 4.4.0

общо-взето няма обяснение защо се случва, но някои версии наистина се държат като българска министърка...

опита ми показва, че членовете на структурата трябва да се подредят по големина - първи са най-големите, масиви и т.н., след това по-малките. каткто е при теб 8-8-32-8-8, някъде по средата се получава фалшиво алайнване в което няма логика, но е факт че получаваш 66 бита. особено често се случва на 64-бита компилатора. ако не ти трябват наистина 64, пусниго форс в 32, може и да ги събере правилно. пробвай и да ги преподредиш.

Автор:  Цецо [ Пет Сеп 16, 2016 8:01 pm ]
Заглавие:  Re: __attribute__ ((__packed__)), GCC > 4.4.0

Е то хубаво ще ги преподреди, а ако става въпрос за предварително зададен патерн? Например хедър на някакъв блок или нещо в протокол?
Не може да не работи, нещо има гнило, това си е крайъгълен камък....

Автор:  [ Пет Сеп 16, 2016 8:07 pm ]
Заглавие:  Re: __attribute__ ((__packed__)), GCC > 4.4.0

Става дума структура, която се търкаля напред-назад между 64, 32, 16 и 8-битови процесори,
По принцип, работеше в GCC 4.4.0, интересно защо обаче в новите GCC са го прецакали. Или може би of C++11 ?
Няма значение колко битов е компилатора, и при 32, и при 64-бита дава един и същи резултат. Не съм още
погледнал дали и при микроконтролери няма да се получи изненада. То всъщност навсякъде при компилация
правя проверки колко ще ми върне sizeof() за конкретните структури, та ще ми изплюе warning ако се получи
разминаване :-)

Автор:  ДедоБоре [ Пет Сеп 16, 2016 8:26 pm ]
Заглавие:  Re: __attribute__ ((__packed__)), GCC > 4.4.0

Цецо написа:
Не може да не работи, нещо има гнило, това си е крайъгълен камък....

така е, ама бозата е факт

виж този бъг

__attribute__((packed)) doesn't work on mingw32 targets since ms-bitfields became the default
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991

препоръчват да се компилира с -mno-ms-bitfields

Автор:  woody [ Пет Сеп 16, 2016 8:45 pm ]
Заглавие:  Re: __attribute__ ((__packed__)), GCC > 4.4.0

GCC 4.9.2 на Линукс се държи нормално, та като нищо е mingw болежка.

Автор:  [ Пет Сеп 16, 2016 9:39 pm ]
Заглавие:  Re: __attribute__ ((__packed__)), GCC > 4.4.0

Мда, това е, което ДедоБоре изрови, потвърдено с g++ -mno-ms-bitfields
MinGW 32/64-бита пакетира правилно променливите. Голямо Благодаря :-)

За тези, които използват Qt Creator, параметри към GCC се подават като в
*.pro файла се вмъкне QMAKE_CXXFLAGS += , например:
Код:
QMAKE_CXXFLAGS += -mno-ms-bitfields

Автор:  ДедоБоре [ Пет Сеп 16, 2016 11:02 pm ]
Заглавие:  Re: __attribute__ ((__packed__)), GCC > 4.4.0

крушката си имала дръжка (от gcc internals)
Цитат:
Target Hook: bool TARGET_MS_BITFIELD_LAYOUT_P (const_tree record_type)

This target hook returns true if bit-fields in the given record_type are to be laid out following the rules of Microsoft Visual C/C++, namely:

(i) a bit-field won't share the same storage unit with the previous bit-field if their underlying types have different sizes, and the bit-field will be aligned to the highest alignment of the underlying types of itself and of the previous bit-field; (ii) a zero-sized bit-field will affect the alignment of the whole enclosing structure, even if it is unnamed; except that (iii) a zero-sized bit-field will be disregarded unless it follows another bit-field of nonzero size. If this hook returns true, other macros that control bit-field layout are ignored.

When a bit-field is inserted into a packed record, the whole size of the underlying type is used by one or more same-size adjacent bit-fields (that is, if its long:3, 32 bits is used in the record, and any additional adjacent long bit-fields are packed into the same chunk of 32 bits. However, if the size changes, a new field of that size is allocated). In an unpacked record, this is the same as using alignment, but not equivalent when packing.

If both MS bit-fields and ‘__attribute__((packed))’ are used, the latter will take precedence. If ‘__attribute__((packed))’ is used on a single field when MS bit-fields are in use, it will take precedence for that field, but the alignment of the rest of the structure may affect its placement.


така че очевидно случката може да се случи на всякакъв компилатор, просто зависи дали ms-bitfields е компилиран по дефолт.
до сега бях попадал на това явление и за мен имаше необичаен/стихиен характер.

все още не мога да преценя дали е бъг в плейсера или наистина е симулация на поведение на М$ компилатор. някой може ли да го пробва на вижуал С какво се получава?

Страница 1 от 1 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/