Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712

Выравнивание и объекты в "сырой" памяти

30.12.2020, 10:34. Показов 2956. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет всем. Нужна помощь гуру С++ со знаниями стандарта.
Есть буфер, в котором лежит значение типа int. Нужно работать с этим значением (читать и писать). Для этого я использую placement new:
C++
1
2
3
4
5
6
7
8
9
// Есть сырой буфер, в котором с индекса 1 лежит значение int
char buffer[64];
 
// Создам на этом буфере в нужном месте объект int
int* pi = new (buffer + 1) int;
 
// Работа с данными
*pi = 777;
int i = *pi;
Но мне говорят, что такой код - это UB, так как адрес buffer + 1 может не быть кратным размеру типа int. Это так?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
30.12.2020, 10:34
Ответы с готовыми решениями:

Возможно ли получение аммониевых кислот из сырой нефти? Возможно ли получение пороха из сырой нефти?
1) Возможно ли получение аммониевых кислот из сырой нефти? 2) Возможно ли получение пороха из сырой нефти, в частности путём получения...

Выравнивание памяти в stm32
Соственно сабж Нигде не найду как организована память. В документации по этому поводу нашел только, что выбирать из памяти можно...

Выравнивание адреса памяти
Прочитал на разных ресурсах про выравнивание адреса данных, но многое ещё не понятно. Чего я понял: Выравнивание адреса нужно для...

20
Злостный нарушитель
 Аватар для Verevkin
10242 / 5670 / 1260
Регистрация: 12.03.2015
Сообщений: 26,265
30.12.2020, 11:18
Цитата Сообщение от d7d1cd Посмотреть сообщение
C++
1
2
// Создам на этом буфере в нужном месте объект int
int* pi = new (buffer + 1) int;
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.12.2020, 11:19
d7d1cd, в целом да. Успешность невыровненного доступа зависит от платформы. Где-то просто будет медленнее работать, где-то будет системное прерывание.

Добавлено через 23 секунды
Verevkin, конечно.
0
Злостный нарушитель
 Аватар для Verevkin
10242 / 5670 / 1260
Регистрация: 12.03.2015
Сообщений: 26,265
30.12.2020, 11:22
Цитата Сообщение от d7d1cd Посмотреть сообщение
Но мне говорят, что такой код - это UB, так как адрес buffer + 1 может не быть кратным размеру типа int. Это так?
Быстрее всего просто тупо посмотреть под дебаггером значения адресов. Т.е. убдиться, как компайлер интерпретирует этот +1 к адресу - как char или как int. От этого и плясать.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.12.2020, 11:28
d7d1cd, memcpy в помощь. Или забить.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
30.12.2020, 11:36  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
d7d1cd, в целом да. Успешность невыровненного доступа зависит от платформы. Где-то просто будет медленнее работать, где-то будет системное прерывание.
А существует ли способ работы с данными в буфере без неопределенного поведения? Я пробовал как показано ниже, но мне сказали, что UB никуда не делось .
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <new>
 
 
#pragma pack(1)
struct IntWrap { int i; };
#pragma pop
 
 
int main(int argc, char** argv)
{
    // Есть сырой буфер, в котором с индекса 1 лежит значение int
    char buffer[64];
 
    // Создам на этом буфере в нужном месте объект IntWrap
    IntWrap* iw = new (buffer + 1) IntWrap;
 
    // Запишу в сырой буфер число. Есть ли здесь UB?
    *static_cast<int*>(IntWrap) = 777;
 
    // Прочитаю из сырого буфера число. Есть ли здесь UB?
    int i = *static_cast<int*>(IntWrap);
}
Добавлено через 45 секунд
Цитата Сообщение от DrOffset Посмотреть сообщение
d7d1cd, memcpy в помощь. Или забить.
В каком смысле забить? Задачу то надо решить.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.12.2020, 11:42
d7d1cd, если ваша программа живёт на платформе, на которой нет проблем с невыровненным доступом (например, intel), то можно забить.

А так, я уже сказал как это решается - через memcpy.
0
фрилансер
 Аватар для Алексей1153
6444 / 5639 / 1128
Регистрация: 11.10.2019
Сообщений: 15,005
30.12.2020, 11:42
d7d1cd, а для чего так дробить память? Чем не устраивает структура навроде

C++
1
2
3
4
5
6
7
8
9
#pragma pack(push,1)
struct mystruct
{
   char c{};
   int32_t i{};
   char reserv[59]{};
};
#pragma pack(pop)
static_assert(sizeof(mystruct)==64);
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.12.2020, 11:43
Алексей1153, это тоже самое только более засахарено и проблемы имеет те же.
0
фрилансер
 Аватар для Алексей1153
6444 / 5639 / 1128
Регистрация: 11.10.2019
Сообщений: 15,005
30.12.2020, 11:44
DrOffset, если проблемы те же, то выбор очевиден
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.12.2020, 11:47
Алексей1153, так суть вопроса темы не в выборе представления данных, а в решении проблем с выравниванием.
0
фрилансер
 Аватар для Алексей1153
6444 / 5639 / 1128
Регистрация: 11.10.2019
Сообщений: 15,005
30.12.2020, 11:51
Цитата Сообщение от d7d1cd Посмотреть сообщение
Есть буфер, в котором лежит значение типа int. Нужно работать с этим значением (читать и писать)
обычная задача парсинга (например, пакеты из железяк). Что тут можно ещё особо придумать, кроме как описание в виде выровненной структуры?

Добавлено через 1 минуту
ну нет, придумать можно - поменять формат данных в этой железяке
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.12.2020, 11:57
d7d1cd, тут нет, кстати, неопределенного поведения. Тут implementation defined поведение.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
30.12.2020, 12:18  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
если ваша программа живёт на платформе, на которой нет проблем с невыровненным доступом (например, intel), то можно забить.
А как узнать, есть ли проблема с не выровненным доступом на моей платформе?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.12.2020, 12:26
d7d1cd, документацию посмотреть.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
30.12.2020, 14:41  [ТС]
DrOffset, что конкретно искать? Может есть какие-то ключевые слова? Документации гигабайты.

Добавлено через 2 часа 0 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
ут нет, кстати, неопределенного поведения. Тут implementation defined поведение.
А можно ссылку на документ, где об этом говорится?
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
30.12.2020, 15:46
Цитата Сообщение от d7d1cd Посмотреть сообщение
DrOffset, что конкретно искать? Может есть какие-то ключевые слова?
Архитектура процессора (который используется), выравнивание данных.

Добавлено через 3 минуты
Цитата Сообщение от d7d1cd Посмотреть сообщение
Я пробовал как показано ниже
Вариант с memcpy()


C++
1
2
3
4
5
6
7
8
9
10
11
int main()
{
    char buffer[64];
 
 
    int iw_val = 777;
    memcpy(buffer + 1, &iw_val, sizeof(int));
 
    int i;
    memcpy(&i, buffer + 1, sizeof(int));
}
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
30.12.2020, 15:58
Цитата Сообщение от d7d1cd Посмотреть сообщение
// Есть сырой буфер, в котором с индекса 1 лежит значение int
char buffer[64];
А выделенные на стеке объекты разве выравниваются? Здесь buffer всегда будет начинаться с чётного адреса?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.12.2020, 19:32
Цитата Сообщение от d7d1cd Посмотреть сообщение
А можно ссылку на документ, где об этом говорится?
У меня нет такой ссылки. Но я исхожу из того, что стандарт C++ считает вот такое размещение объекта в готовой памяти корректным. Тут нет неопределенного поведения (если кто-то вспомнит про strict aliasing, то именно в данном случае с ним проблемы нет):
Цитата Сообщение от d7d1cd Посмотреть сообщение
C++
1
int* pi = new (buffer + 1) int;
А вот что произойдет, если мы в результате этого получим указатель (pi) с невыровненным адресом и будем его использовать для доступа, в стандарте C++ вообще не оговаривается (в отличие от стандарта С, в котором это явным образом UB). Предельно формально, с точки зрения С++, эта ситуация должна рассматриваться как UB (потому что если нет текста в стандарте по этому поводу, то это автоматически означает UB), но тут на помощь нам приходит здравый смысл совместно с документацией на платформу, в которой эта вещь четко прописана.
Вот, например, для Intel про это написано здесь.
0
 Аватар для eva2326
1673 / 501 / 107
Регистрация: 17.05.2015
Сообщений: 1,518
31.12.2020, 14:11
Цитата Сообщение от DrOffset Посмотреть сообщение
если мы в результате этого получим указатель (pi) с невыровненным адресом и будем его использовать для доступа, в стандарте C++ вообще не оговаривается
Оговаривается.
- В стандарте полным полно мест, которые затрагивают вопросы выравнивания для объектов.
- В стандарте полным полно инструментов контроля за выравниванием.
- В стандарте куча мест, где указывается, что несоблюдения требований может приводить к UB

Например в данном тезисе перечисляются требования без которых объект не сможет начать жить:
6.7.3 Lifetime
- storage with the proper alignment and size for type T is obtained

А вот здесь прямым текстом сообщается, что будет при попытке доступа к неживому объекту:
The program has undefined behavior if:
- the pointer is used to access a non-static data member or call a non-static member function of the object
Если покапаться, наверняка ещё можно найти ножество цитат, где прямым или косвенным образом дают понять, что будет, если нарушать требования.

Цитата Сообщение от DrOffset Посмотреть сообщение
на помощь нам приходит здравый смысл
Здравый смысл подсказывает: проблема с выравниванием - аппаратная, а не софтверная.
Поэтому, то, что язык си трактует как UB, никуда не делось и в с++.

В самой фразе: "требования к выравниванию" не просто так используется слово: "требование".
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
31.12.2020, 14:11
Помогаю со студенческими работами здесь

Выравнивание памяти под 16
Hello, всем привет! Хочу выровнять массив НОРМАЛЬНО, чтобы вместо movups юзать movaps, что в будущем даст ещё пару миллисекунд...

Выравнивание структуры в памяти
Как выровнять в памяти структуры? struct Foo { char c; struct Bar *p; short x; }; struct Bar { char c; short d; ...

Выравнивание в динамической памяти
char * c = new char{}; char * cc = new char{}; std::cout &lt;&lt; cc - c &lt;&lt; std::endl; Выводит 32, понятно почему. но вот это...

Выравнивание сегмента памяти
Дано задание:Захватить один кусок памяти размером N Кбайт. Заполнить его нулями. Захватить другой кусок памяти размером M Кбайт памяти и...

Выравнивание памяти и скорость работы.
Есть ли преимущество использования переменных длинной в 4 байта в 32 битных процессорах ARM в смысле скорости? Помнится мне, в 32 битных...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru