Информация об изменениях

Сообщение Re: [C] как разместить структуру внутри буфера от 27.02.2019 11:53

Изменено 27.02.2019 16:55 watchmaker

Re: [C] как разместить структуру внутри буфера
Здравствуйте, B0FEE664, Вы писали:


BFE>Допустим у меня есть предзаказанный буфер длиною N и я хочу внутри него разместить несколько разных экземпляров разных структур. Как это сделать правильно?


Твой вариант в общем-то норм, но в нём будет проблема с выравниванием.

Если есть структуры struct S1 { char data; } и struct S4 { int data; }, то вызов Create_S1(), за которым следует Create_S4(), приведёт к тому, что поля второй структуры будут неверно выровнены (при допущении, что sizeof(int) > 1 и при естественном допущении, что изначально буфер был выровнен, например, из-за того, что был получен вызовом malloc).

То есть необходимо перед "выделением" памяти проверять значение tail и довыравнивать его при необходимости.
Например, как-то так:
uintptr_t uiTail = (uintptr_t)(pBuffer->tail);
uiTail = (uiTail + (_Alignof(MyStruct) - 1)) % _Alignof(MyStruct); // тут педанты могут ещё проверить на переполнение
char* tail = (сhar*)uiTail; // теперь дальше нужно использовать этот tail вместо (pBuffer->tail)

if ( pBuffer->end < tail + sizeof(MyStruct) ) // тут формально тоже может быть переполнение, на которое можно проверить
    return NULL;


MyStruct* pNewObj = (MyStruct*)tail;

pBuffer->tail = (char*)(pNewObj + 1);


BFE>typedef struct

BFE>{
BFE> const char* begin;
BFE> const char* end;
BFE> const char* tail;
BFE>} Buffer;
Занимательно, что функция выделения памяти хранить указатели на const, а выдаёт наружу указатели без const. Интересно, из каких соображений этот const в Buffer появился?
Re: [C] как разместить структуру внутри буфера
Здравствуйте, B0FEE664, Вы писали:


BFE>Допустим у меня есть предзаказанный буфер длиною N и я хочу внутри него разместить несколько разных экземпляров разных структур. Как это сделать правильно?


Твой вариант в общем-то норм, но в нём будет проблема с выравниванием.

Если есть структуры struct S1 { char data; } и struct S4 { int data; }, то вызов Create_S1(), за которым следует Create_S4(), приведёт к тому, что поля второй структуры будут неверно выровнены (при допущении, что sizeof(int) > 1 и при естественном допущении, что изначально буфер был выровнен, например, из-за того, что был получен вызовом malloc).

То есть необходимо перед "выделением" памяти проверять значение tail и довыравнивать его при необходимости.
Например, как-то так:
uintptr_t uiTail = (uintptr_t)(pBuffer->tail);
uiTail = (uiTail + (_Alignof(MyStruct) - 1)) / _Alignof(MyStruct) * _Alignof(MyStruct); // тут педанты могут ещё проверить на переполнение
char* tail = (сhar*)uiTail; // теперь дальше нужно использовать этот tail вместо (pBuffer->tail)

if ( pBuffer->end < tail + sizeof(MyStruct) ) // тут формально тоже может быть переполнение, на которое можно проверить
    return NULL;


MyStruct* pNewObj = (MyStruct*)tail;

pBuffer->tail = (char*)(pNewObj + 1);


BFE>typedef struct

BFE>{
BFE> const char* begin;
BFE> const char* end;
BFE> const char* tail;
BFE>} Buffer;
Занимательно, что функция выделения памяти хранить указатели на const, а выдаёт наружу указатели без const. Интересно, из каких соображений этот const в Buffer появился?