Re[3]: [C] как разместить структуру внутри буфера
От: andrey.desman  
Дата: 27.02.19 15:58
Оценка: 1 (1) +1
Здравствуйте, B0FEE664, Вы писали:

BFE>
BFE>MyStruct* Create_JsnToken(Buffer* pBuffer)
BFE>{
//Это то, на сколько указатель из размера выравнивания выбивается, а не сколько надо добавить, чтобы стать кратным _Alignof(MyStruct).
BFE>  const int nPadding = (pBuffer->tail - (char*)NULL) % _Alignof(MyStruct);
BFE>  if ( pBuffer->end < pBuffer->tail + nPadding + sizeof(MyStruct) )
BFE>
Re: [C] как разместить структуру внутри буфера
От: watchmaker  
Дата: 27.02.19 11:53
Оценка: 4 (1)
Здравствуйте, 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 появился?
Отредактировано 27.02.2019 16:55 watchmaker . Предыдущая версия .
Re: [C] как разместить структуру внутри буфера
От: Mihas  
Дата: 27.02.19 11:14
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:


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

Уж, не union ли тебе нужен? Или я чего не понимаю?
Отредактировано 27.02.2019 11:15 Mihas . Предыдущая версия .
Re[3]: [C] как разместить структуру внутри буфера
От: watchmaker  
Дата: 27.02.19 15:47
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

BFE> Правильно ли я понимаю, что адрес структуры должен быть кратным _Alignof(имя структуры)?

Да.

BFE>как-то так:

BFE>const int nPadding = (pBuffer->tail — (char*)NULL) % _Alignof(MyStruct);
Нет, тут неверно.
Re[3]: [C] как разместить структуру внутри буфера
От: Mr.Delphist  
Дата: 28.02.19 09:35
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

BFE>Зачем мне выравнивать размер структуры? Структуры разные и разного размера должны лежать в одном буфере. Выравнивать все по одному размеру — зря расходовать память.

В ряде случаев, выравнивание увеличивает эффективность обмена между памятью и процессором. Ещё в ряде случаев, процессор просто пошлёт программиста читать маны при первой же попытке обратиться к невыровненным данным.
Re[6]: [C] как разместить структуру внутри буфера
От: watchmaker  
Дата: 03.03.19 10:51
Оценка: +1
Здравствуйте, _NN_, Вы писали:

BFE>>А разве представление отрицательных чисел в дополнительном коде гарантируется стандартом C?


_NN>Скоро будет


Твоя ссылка про другой язык — не про C.
Re[7]: [C] как разместить структуру внутри буфера
От: _NN_ www.nemerleweb.com
Дата: 03.03.19 11:39
Оценка: +1
Здравствуйте, watchmaker, Вы писали:

_NN>>Скоро будет


W>Твоя ссылка про другой язык — не про C.


Ну да, там C++..
На данный момент С11 позволяет выбрать одну из 3-х реализаций.
Возможно в C сдадутся
http://rsdn.nemerleweb.com
http://nemerleweb.com
[C] как разместить структуру внутри буфера
От: B0FEE664  
Дата: 27.02.19 09:40
Оценка:
Как на C написать placement new для различных структур?

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

typedef struct
{
 ...
} MyStruct;

typedef struct
{
  const char* begin;
  const char* end;
  const char* tail;
} Buffer;

MyStruct* Create_MyStruct(Buffer* pBuffer)
{
  if ( NULL == pBuffer )
    return NULL;

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

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

  return pNewObj;
}
И каждый день — без права на ошибку...
Re: [C] как разместить структуру внутри буфера
От: kov_serg Россия  
Дата: 27.02.19 10:37
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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



BFE> pBuffer->tail += sizeof(MyStruct); // _Alignof(MyStruct) ?

У вас размер структуры должен быть выравнен (paddings). Достаточно что бы начало вашего региона было выравнено.
А так можете вручную выравнивать если память линейная
#define align(x,n) ((char*)(x)+(-(int)(char*)(x)&(n-1)))
Отредактировано 27.02.2019 10:42 kov_serg . Предыдущая версия .
Re[2]: [C] как разместить структуру внутри буфера
От: B0FEE664  
Дата: 27.02.19 10:54
Оценка:
Здравствуйте, kov_serg, Вы писали:

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

BFE>> pBuffer->tail += sizeof(MyStruct); // _Alignof(MyStruct) ?
_>У вас размер структуры должен быть выравнен (paddings).
Зачем мне выравнивать размер структуры? Структуры разные и разного размера должны лежать в одном буфере. Выравнивать все по одному размеру — зря расходовать память.

_>Достаточно что бы начало вашего региона было выравнено.

разве?

_>А так можете вручную выравнивать если память линейная

Память линейная, но я не понимаю как это применять:
_>
_>#define align(x,n) ((char*)(x)+(-(int)(char*)(x)&(n-1)))
_>
И каждый день — без права на ошибку...
Re[3]: [C] как разместить структуру внутри буфера
От: Sergey_BG Россия  
Дата: 27.02.19 11:18
Оценка:
Здравствуйте, B0FEE664, Вы писали:
BFE>разве?

Я прочитал что такое alignof и увидел, что оно возвращает что задаёт alignas. А последнее это аналог pragma pack. Т.е. Для структуры он задаёт выравнивание полей по некоторому размеру.
Т.е. размер струтуры от этого меняется, так как меняется положение полей внутри структуры. И для массива одинаковых структур, вам достаточно выравнять положение первого элемента массива. sizeof вернёт размер кратный выравниванию. И следующая структура будет тоже выравнена. Для разных структур, надо выравнивать каждую структуру.
Сергей
Отредактировано 27.02.2019 12:11 Sergey_BG . Предыдущая версия .
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 появился?

Этот код из головы.
И каждый день — без права на ошибку...
Re[3]: [C] как разместить структуру внутри буфера
От: kov_serg Россия  
Дата: 27.02.19 15:44
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Зачем мне выравнивать размер структуры? Структуры разные и разного размера должны лежать в одном буфере. Выравнивать все по одному размеру — зря расходовать память.

Выравнивают не для экономии памяти, а для уменьшения количества обращений к памяти (которая читается в кэш блоками). Так что не заморачивайтесь и выравнивайте например по 16 байт все свои разные структуры.

_>>Достаточно что бы начало вашего региона было выравнено.

BFE>разве?
У вас была всего одна структура. И если она кратна 4 байтам и выравнивание у вас 4 байта, то это будет сохраняться.

_>>А так можете вручную выравнивать если память линейная

BFE>Память линейная, но я не понимаю как это применять:
_>>
_>>#define align(x,n) ((char*)(x)+(-(int)(char*)(x)&(n-1)))
_>>

   struct A { ... };
   enum { sizeof_A4=(sizeof(struct A)+3)&~3 };
   enum { sizeof_A8=(sizeof(struct A)+7)&~7 };
   enum { sizeof_A16=(sizeof(struct A)+15)&~15 };
   ...
   char *x=0; int dx=123, dxa=dx, a=8;
   x+=dx;
   x=x+(-(int)x&(a-1))); // выравниваем на 8
   x=align(x,a);         // тоже самое - выравниваем на 8
   dxa=(dxa+a-1)&(a-1);  // выравниваем размер на 8
   x+=dxa;               // выравнивание сохраняется
Re[4]: [C] как разместить структуру внутри буфера
От: B0FEE664  
Дата: 01.03.19 09:20
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>>>
_>   x=x+(-(int)x&(a-1))); // выравниваем на 8
_>

А разве представление отрицательных чисел в дополнительном коде гарантируется стандартом C?
И каждый день — без права на ошибку...
Re[5]: [C] как разместить структуру внутри буфера
От: kov_serg Россия  
Дата: 01.03.19 10:35
Оценка:
Здравствуйте, B0FEE664, Вы писали:
_>>>>
_>>   x=x+(-(int)x&(a-1))); // выравниваем на 8
_>>

BFE>А разве представление отрицательных чисел в дополнительном коде гарантируется стандартом C?
Вам шашечки или ехать?
Re[6]: [C] как разместить структуру внутри буфера
От: B0FEE664  
Дата: 01.03.19 12:09
Оценка:
Здравствуйте, kov_serg, Вы писали:

BFE>>А разве представление отрицательных чисел в дополнительном коде гарантируется стандартом C?

_>Вам шашечки или ехать?

шашечки.
И каждый день — без права на ошибку...
Re[5]: [C] как разместить структуру внутри буфера
От: _NN_ www.nemerleweb.com
Дата: 03.03.19 10:13
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, kov_serg, Вы писали:


_>>>>
_>>   x=x+(-(int)x&(a-1))); // выравниваем на 8
_>>

BFE>А разве представление отрицательных чисел в дополнительном коде гарантируется стандартом C?

Скоро будет
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[6]: [C] как разместить структуру внутри буфера
От: kov_serg Россия  
Дата: 03.03.19 11:09
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Скоро будет

Вот не очень понятно чем модульная арифметика им не угодила.
Видимо очень хотят новых граблей в виде a+b+c != a+c+b и других прелестей.
Re[7]: [C] как разместить структуру внутри буфера
От: watchmaker  
Дата: 03.03.19 11:21
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Вот не очень понятно чем модульная арифметика им не угодила.

Ну написали же:

over 90% of all overflow is a bug, and defining wrapping behavior would not have solved the bug.

и пару других причин.

И сделав переполнение определённым ты лишишь санитайзеры возможности находить ошибки в коде: в исходниках ведь не написано для каждой арифметической операции является ли переполнение в ней желаемым поведением или программист просто забыл его проверить.
Re[8]: [C] как разместить структуру внутри буфера
От: kov_serg Россия  
Дата: 03.03.19 14:43
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Здравствуйте, kov_serg, Вы писали:


_>>Вот не очень понятно чем модульная арифметика им не угодила.

W>Ну написали же:
W>

over 90% of all overflow is a bug, and defining wrapping behavior would not have solved the bug.

W>и пару других причин.

W>И сделав переполнение определённым ты лишишь санитайзеры возможности находить ошибки в коде: в исходниках ведь не написано для каждой арифметической операции является ли переполнение в ней желаемым поведением или программист просто забыл его проверить.


В отличии от модульной арифметики, арифметика которую предлагают противоречивая и содержит больше проблем чем решает. Но походы по граблям еще предстоят. Например в webassembly ввернули проверку на переполнение и получили неожиданные эффекты.
Подобная арифметика нужна только для очень векторных операций, что бы не угробить эффект от векторизации.
Re: [C] как разместить структуру внутри буфера
От: MasterZiv СССР  
Дата: 04.03.19 12:52
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Как на C написать placement new для различных структур?


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


BFE>
BFE>typedef struct
BFE>{
BFE> ...
BFE>} MyStruct;

BFE>typedef struct
BFE>{
BFE>  const char* begin;
BFE>  const char* end;
BFE>  const char* tail;
BFE>} Buffer;

BFE>MyStruct* Create_MyStruct(Buffer* pBuffer)
BFE>{
BFE>  if ( NULL == pBuffer )
BFE>    return NULL;

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

BFE>  MyStruct* pNewObj = (MyStruct*)pBuffer->tail;
BFE>  pBuffer->tail += sizeof(MyStruct);  // _Alignof(MyStruct) ?

BFE>  return pNewObj;
BFE>}
BFE>


от начала буфера размещаешь последовательно все структуры, пока хватает длины буфера,
на каждом шаге увеличиваешь указатель (void* или char*) на размер (sizeof) очередной
размещаемой структуры.
Re[2]: [C] как разместить структуру внутри буфера
От: B0FEE664  
Дата: 04.03.19 13:55
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>от начала буфера размещаешь последовательно все структуры, пока хватает длины буфера,

MZ>на каждом шаге увеличиваешь указатель (void* или char*) на размер (sizeof) очередной
MZ>размещаемой структуры.

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