LINUX.ORG.RU

std::map memcpy

 


0

2

Как скопировать std::map в память и потом вытащить ее оттуда?
Пример

std::map<std::string, std::any> _params;

uint8_t authorization_type = 77;
vector<uint8_t> password = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };

_params["authorization_type"] = authorization_type;
_params["password"] = password;

void* ptr = malloc(sizeof (_params));

memcpy(ptr, &_params, sizeof (_params));

Далее пытаюсь привести к указателю, получить значения мапа и получаю ошибку

std::map<std::string, std::any>* after_params = reinterpret_cast<std::map<std::string, std::any>*>(ptr);

uint8_t test = std::any_cast<uint8_t>((*after_params)["authorization_type"]);



Последнее исправление: nzimvf (всего исправлений: 1)

Ответ на: комментарий от tyro33

да вспомнил, хитропопый стрикт алиясинг не раз ломал мне код

anonymous
()
Ответ на: комментарий от tyro33

никакое.

C++ говорит «Every value of pointer type is one of the following: ». «Никакого» в списке following нет.

эффективный тип будет определен при первой записи

И сейчас ты принесёшь определение эффективного типа в C++.

utf8nowhere ★★★
()
Ответ на: комментарий от anonymous

берем указатель на воид, маллочим с запасом 12 байт
кастуем к флоату и пишем туда флоат

А как пишем?

utf8nowhere ★★★
()
Ответ на: комментарий от KennyMinigun

В результате b может быть 3 вместо ожидаемого 4.

Немного запутался. Может быть в данном случае: «b может быть 5 вместо ожидаемого 4.» ?

Если нет, то можно немного подробностей почему 3 вместо 4?

Kronick
()
Ответ на: комментарий от nzimvf

это только в случае cv квалификаторов компилятор в переменную b запишет 3 вместо ожидаемого 4 до placement-new или во всех случаях?

Нет, там ключевое слово *может*. На то оно и undefined behavior: не можно сказать что конкретно сделает компилятор/оптимизатор. В данном случае, как показал выше анонимус std::launder можно трактовать как барьер памяти.

KennyMinigun ★★★★★
()
Ответ на: комментарий от yyk

тогда компилятор не сможет сделать проверку типов. и скорее всего эффективный тип указателю, возвращенному malloc, назначен не будет. а значит все легально
тогда автор кода сам должен гарантировать, что правильно работает с указателем, когда читает из него данные после вызова такой цепочки функций (в данном случае - приводит к корректному типу). короче, все то же самое, что и с другими функциями, которые принимают void*

tyro33
()
Ответ на: комментарий от utf8nowhere

C++ говорит «Every value of pointer type is one of the following: ». «Никакого» в списке following нет.

malloc просто выделает память и не заботится о типе объекта, который будет там лежать. поэтому с void*, который он возвращает никакой тип не связан. можно буквоедствовать сколь угодно, как правильно обозвать «значение», но смысл не изменится

И сейчас ты принесёшь определение эффективного типа в C++.

смысл ходить вокруг да около? давайте уж сразу посмотрим, как это работает:

If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value.
For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.

tyro33
()
Ответ на: комментарий от tyro33

смысл ходить вокруг да около? давайте уж сразу посмотрим, как это работает:

(Версию драфта,) номер раздела, номер параграфа откуда скопирована цитата можно увидеть?

utf8nowhere ★★★
()
Ответ на: комментарий от Deleted

и вы утверждаете что там по прежнему будет флоат ?

Начиная с c++17

Ни до C++17, ни после там нет float-а, если под «кастуем к флоату и пишем туда флоат» имеется в виду что-то типа *static_cast<float*>(ptr_to_void) = <какое-то значение>.

utf8nowhere ★★★
()
Последнее исправление: utf8nowhere (всего исправлений: 1)
Ответ на: комментарий от KennyMinigun

кстати если компилер не поддерживает launder и у нас не винда, то фоли использует асм вставку, которую можно трактовать как «загрузка значения в регистр»
тоесть во преки компилятору который может где то там по пути наоптимайзить, эта асм вставка говорит загрузите мне еще раз значение в регистр перед использованием, если сравнивать с барьером то наверное лучше взять обычную строгость чтения, хз зачем там в студии полный пихают, может в студии других нет

anonymous
()
Ответ на: комментарий от Kronick

Немного запутался. Может быть в данном случае: «b может быть 5 вместо ожидаемого 4.» ?

Да, прошу прощения, опечатка. Надо было «b может быть 3 вместо ожидаемого 5.»

struct X {
  const int n; // note: X has a const member
  int m;
};

  X *p = new X{3, 4};
  const int a = p->n;
  X* np = new (p) X{5, 6};
  const int b = p->n; // undefined behavior 

Сначала X(*p).n инициализуется в 3, потом placement new заменяет его реальное значение на 5. Однако компилятор зная, что чтение после placement new — UB делает (например) constant propagation и пишет

const int a = 3;
const int b = 3;

А может потом и вовсе обьединить две константы в одну. Но опять же — лишь спекуляция на тему возможной реализации в случае UB.

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 1)
Ответ на: комментарий от utf8nowhere

*static_cast<float*>(ptr_to_void) = <какое-то значение>

new (ptr_to_void) float(...) - чёт забыл, вот так float будет

Пруф

На то что new создаёт объект? Не, я не настолько хорошо стандарт знаю

Deleted
()
Ответ на: комментарий от Deleted

new (ptr_to_void) float(...) - чёт забыл, вот так float будет

С этим согласен.

На то что new создаёт объект?

Нет, на это пруфов не надо.

utf8nowhere ★★★
()
Ответ на: комментарий от utf8nowhere

Затупил я что-то с присвоением, бывает же

Deleted
()

Почитал я тут про std::launder https://en.cppreference.com/w/cpp/utility/launder
Какие то одноразовые константы которые не константы и попытки их менять костылями через перезапись памяти. У кого такие странные задачи - непонятно.

По сабжу. Только сериализовать.
Но есть один фокус. ЕМНИП для std::map (как и в любого другого контейнера) можно задать свой аллокатор. Соответственно все данные std::map это сам инстанц std::map + его персональная куча. Те делай копию инстанца и копию кучи и должно получится. Хотя адреса скорее всего поедут при восстановлении и тут придется сильно подумать.

bga_ ★★★★
()
Ответ на: комментарий от utf8nowhere

Это С стандарт, если что. Собсна, сама malloc - сишная функция. Все, что тебе нужно из стандарта С++ в данном случае - это строчка:

Effects: These functions have the semantics specified in the C standard library.

Поэтому, если хочешь знать, что возвращает malloc и как с этим работать - смотри стандарт С. А там мы видим:

The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object

То есть возвращаемый объект не имеет объявленного типа со всеми вытекающими. В том числе правилами определения типа для такого объекта, которые я цитировал выше.
С++ стандарт в данном случае отсылает в С, какие могут быть вопросы? Не согласны - давайте номер раздела, параграфа из С++ стандарта, где написано, что совместимость - гомно и с malloc в крестах работается иначе.

tyro33
()
Ответ на: комментарий от tyro33

С++ стандарт в данном случае отсылает в С

В случае malloc да, отсылает. Но ты пытался втереть про effective type, а теперь вильнул в сторону описания malloc.

Не виляй, неси определение effective type в C++ или хотя бы место, где идёт отсылка к этому определению в стандарте C.

utf8nowhere ★★★
()
Последнее исправление: utf8nowhere (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.