Re[2]: [C] как разместить структуру внутри буфера
От: B0FEE664  
Дата: 27.02.19 14:18
Оценка:
Здравствуйте, watchmaker, Вы писали:

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

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

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

W>То есть необходимо перед "выделением" памяти проверять значение tail и довыравнивать его при необходимости.
Я так и думал. Правильно ли я понимаю, что адрес структуры должен быть кратным _Alignof(имя структуры)?
как-то так:
MyStruct* Create_JsnToken(Buffer* pBuffer)
{
  if ( NULL == pBuffer )
    return NULL;

  const int nPadding = (pBuffer->tail - (char*)NULL) % _Alignof(MyStruct);

  if ( pBuffer->end < pBuffer->tail + nPadding + sizeof(MyStruct) )
    return NULL;

  pBuffer->tail += nPadding;

  MyStruct* pNewObj = (MyStruct*)pBuffer->tail;
  pBuffer->tail += sizeof(MyStruct);  

  return pNewObj;
}


  тут что-то странное
W>Например, как-то так:
W>
W>uintptr_t uiTail = (uintptr_t)(pBuffer->tail);

W>uiTail = (uiTail + (_Alignof(MyStruct) - 1)) % _Alignof(MyStruct); // тут педанты могут ещё проверить на переполнение
// ] uiTail == 20 and _Alignof(MyStruct) == 4 then uiTail == 3 ?

W>char* tail = (сhar*)uiTail; // теперь дальше нужно использовать этот tail вместо (pBuffer->tail)
// char* tail = pBuffer->tail + (сhar*)uiTail; ?

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

W>MyStruct* pNewObj = (MyStruct*)tail;

W>pBuffer->tail = (char*)(pNewObj + 1); // +1 ? Чего-то я не понимаю... 
W>


W>Занимательно, что функция выделения памяти хранить указатели на const, а выдаёт наружу указатели без const. Интересно, из каких соображений этот const в Buffer появился?

Этот код из головы.
И каждый день — без права на ошибку...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.