Перейти к содержанию
    

Указатель на невыровненную память

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

 

Представил как компилятор на это смотрит

 

compil.thumb.jpg.c4fac1f2d3f0bce1ca2ecfbae96080a5.jpg

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, firstvald сказал:

...что будет так же лежать во внешнем компе,  если эти данные используются для передачи в комп или приема из него.

Не так уж много критериев: нужно лишь обеспечить согласованность в "индейцах" (порядке следования байтов внутри машинных слов), направлении битовых полей в структурах и выравнивании. По сути, этого достаточно для взаимодействия с внешним миром:smile:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

предмет дискуссии очень напомнил мне такую штуку. когда микропроцессорная система выглядела как процессор- защелка адреса- озу и пзушка ,  был такой прием: линии адреса и данных озу разводить на плате можно было как угодно - лишь бы было удобно развести. А вовсе не А15 процессора в А15 как в цоколевке ОЗУ. Из за того, что процессор сам для себя писал и читал данные, передавались и читались как надо (они физически в озу могли быть намешаны как угодно). А вот с пзу уже такой фокус не проходил . Вот так же и тут. Пока данные варятся в пределах одного процессора, совершенно не важно, как они лежат в памяти.

 

 

добиться одинакового выравнивания в процессоре и внешнем компе отдельная научно-техническая задача, пахнущая госпремией, ну или еще чем-нибудь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

23 минуты назад, firstvald сказал:

был такой прием: линии адреса и данных озу разводить на плате можно было как угодно - лишь бы было удобно развести...

Этот прием называется своп (swap) и используется ныне повсеместно и весьма часто.
 

Цитата

добиться одинакового выравнивания в процессоре и внешнем компе отдельная научно-техническая задача, пахнущая госпремией, ну или еще чем-нибудь.

Добился - где моя премия?))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 часов назад, Arlleex сказал:

Я указал, что компилятор, видя volatile у объекта, мог сделать предположение, что адрес объекта уже гарантированно выровнен на нужную границу для осуществления корректного доступа, не производящего (возможные) множественные side-effects между двумя точками следования.

Вы слишком глубоко пашете. Так и плуг можно сломать.  :wink:

Мне более интересно решение практических задач. А на практике уже проверили.

И не вижу смысла пытаться достичь корректной работы на всех возможных компиляторах в мире. Имхо - практически это не имеет смысла (если не пишете какую-то универсальную библиотеку для всего). А в общем случае - и невозможно. Как вы сами же убедились уже на Кейле.

Реальные проекты делаются для конкретного железа и на конкретном компиляторе. Попытки универсализировать для всех возможных компиляторов - имхо пустая трата времени. Зачем? если работаем сейчас на этом и пишем для этого?

18 часов назад, Arlleex сказал:

Вот именно, чтобы не выкинул. Я когда убираю volatile, CLang тоже начинает копировать пословно (LDR/STR) для Cortex-M4, и по-байтно для Cortex-M0. Налицо разные подходы к volatile-доступам у GCC и CLang.

Топик вообще не про volatile. Не его здесь обсуждаем.

18 часов назад, Arlleex сказал:

Нет, он все понимает, просто исходит из предположения, что кодер в здравом уме и понимает, что невозможно и рыбку съесть, и кости - вон:smile:

Вот именно - в здравом уме. Значит если метод работает, значит его можно использовать. Может он на другом компиляторе не заработает, так и Вы наверное код своих реальных проектов не на всех существующих в мире компиляторах проверяете? :wink:  И наверняка на каких-то ваш код тоже не правильно скомпилится.

 

PS: Мне вот более важно, чтобы в некоторых реальных моих проектах, некоторый код правильно компилился в IAR на Cortex-M и в VS на x86. Это мне важнее, чем  проверять правильность компиляции на других ARM-компиляторах.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 часов назад, jcxz сказал:

И не вижу смысла пытаться достичь корректной работы на всех возможных компиляторах в мире.

Я тоже не вижу смысла, но иногда полезно просто понимать, на что (возможно) стоит обратить внимание и где ждать потенциальных багов в случае чего. Метод "проверить на своем компиляторе и забыть" рабочий, конечно же, но кто может гарантировать, что перейдя завтра на новую версию одного и того же компилятора не обнаружится, что его разработчики где-то чуть строже отнеслись к стандарту и пользовательский код не сломается в неожиданном месте?

Просто Вы написали, что раз CLang для ARM Cortex-M генерирует LDRD по невыровненному адресу, то в топку его. Именно с этим выводом я был не согласен, потому что на эту тему даже разработчики LLVM (CLang) не один год дискутировали с сообществом разработчиков и комитетом по стандартизации Си. Потому и прибегнул к акценту на volatile-ность и другим интересным деталям Си.

А вот правильность (с точки зрения следования стандарту языка) поведения компилятора вполне может идти вразрез с удобством написания кода. Наверное, это и определяет (для большинства реальных программистов), какие компиляторы "в топку", а какие нет:smile:

Ну и тогда уж, если не сложно, прошу Вас привести листинг следующего теста в IAR

#pragma pack(push, 1)
struct PackStr {
  u64 d64;
};
#pragma pack(pop)

volatile struct {
  u8      d8;
  PackStr p64;
}UnalignStr;

int main() {
  UnalignStr.p64.d64; // <- какая инструкция CPU для Cortex-M4 будет применена?
}


Всякие флаги принудительного невыровненного доступа, если такие есть, должны быть сняты.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 10/19/2023 at 12:38 PM, Arlleex said:

Вполне себе нормальное решение, которое подойдет абсолютно всем.

противоречивое заявление

On 10/19/2023 at 9:24 PM, Arlleex said:

Вообще, стандарт Си говорит, что если указатель на результирующий тип не выровнен на естественную границу этого типа, поведение не определено.

 

Изменено пользователем sasamy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, sasamy сказал:

противоречивое заявление

Можно чуть конкретнее, в чем и где противоречивость?

Если компилятор предоставляет механизмы для работы с упакованными данными (и, соответственно, невыровненными указателями) за счет расширений языка, то грех этим не воспользоваться. Если такой возможности нет, то ничего не мешает вручную перепаковывать такие данные. Да, с точки зрения стандарта любой невыровненный доступ - это UB. Но стандарт не знает о расширениях компиляторов, которые могут позволить взять под контроль операции с такими указателями и обходить UB.

Я писал, что идеального варианта упаковки для всех (и, возможно, будущих) архитектур CPU нет, поэтому достаточно определиться на каком-то одном (варианте) и придерживаться его. И что не имеет смысла тасовать и растаскивать уже по смыслу сгруппированные элементы в структурах по местам, где CPU к ним будет иметь всегда выровненный доступ, особенно при работе с протоколами передачи данных.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 10/21/2023 at 11:32 PM, Arlleex said:

Можно чуть конкретнее, в чем и где противоречивость?

Если компилятор предоставляет механизмы для работы с упакованными данными (и, соответственно, невыровненными указателями) за счет расширений языка, то грех этим не воспользоваться.

это не расширение языка а веник для заметания UB под ковёр, потому что явно противоречит стандарту, странно что вы не видите противоречия в своих высказываниях - в прошлый раз вы утверждали что любое UB в С смертный грех, но оказывается если очень хочется то можно

On 10/21/2023 at 11:32 PM, Arlleex said:

Я писал, что идеального варианта упаковки для всех (и, возможно, будущих) архитектур CPU нет, поэтому достаточно определиться на каком-то одном (варианте) и придерживаться его.

насколько я понял оппонент ваш про маппинг имел ввиду как раз то что в заголовке темы - UB с указателями на невыровненные адреса при прямом маппинге структуры на буфер с данными без сериализации/десериализации

Изменено пользователем sasamy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 часов назад, sasamy сказал:

это не расширение языка а веник для заметания UB под ковёр, потому что явно противоречит стандарту

Именно за счет расширений и можно писать понятный код и писать его проще, ежели как это позволял бы голый стандарт.
 

12 часов назад, sasamy сказал:

странно что вы не видите противоречия в своих высказываниях - в прошлый раз вы утверждали что любое UB в С смертный грех, но оказывается если очень хочется то можно

Да, в общем случае UB может привести к любым результатам - как правильным, так и неправильным. Но практически все современные компиляторы имеют расширения. Всякие __unaligned, __packed, и т.д. - все эти ключевые слова отсутствуют в стандарте, но их четко описывают в документации на компилятор. Тогда с чего компилятор будет генерировать UB?

В прошлый раз (в теме, которую Вы указали) мы обсуждали не UB по выравниванию, а UB из-за доступа к volatile между двумя точками следования. У компилятора на этот счет нет описания в справочнике, а значит имеет смысл делать предположения о следовании его стандарту. Вот и все.

Касательно расширений продолжу.
 

u32 *p = 'address';

Компилятору никаких специальных указаний нет, поэтому он предполагает, что 'p' содержит валидный выровненный указатель. При доступе будет сгенерирована команда чтения/записи 32-битного слова (или кучка команд доступа по частям) - имеет право. Если указатель не выровнен, то поведение не определено: если компилятор уже знает о том, что адрес не выровнен, то ассемблерный листинг может весьма удивить. В противном случае лишь юзер может знать, во что выльется (возможное) применение невыровненного доступа на его процессоре.
 

__unaligned u32 *p = 'address';

Компилятор заранее наделили знанием, что указатель может содержать невыровненный адрес. Тут UB с точки зрения выравнивания нет. Компилятор сгенерирует любую из удобных (поддерживаемых CPU) инструкций доступа по адресу в 'p'.
 

u32 volatile *p = 'address';

Компилятор предполагает, что 'p' содержит выровненный указатель. В отличие от первого случая, процессор не может читать/писать значение по указателю "частями", потому что это нарушит семантику обращений/изменений volatile-объекта между двумя точками следования. Поэтому компилятор строго предполагает, что адрес тут точно выровнен, и никак иначе. Он однозначно генерирует инструкцию 32-битного доступа. Если же в этот указатель каким-то образом поместился невыровненный указатель (динамически, в run-time), то, как и в первом случае, лишь юзеру будет ясно, чем это чревато. Если же компилятор на этапе компиляции уже будет видеть неровный указатель - UB, может такой доступ запросто вовсе выкинуть из кода, прихватив все зависимое.
 

__unaligned u32 volatile *p = 'address';

Итак, у 'p' два атрибута: __unaligned и квалификатор volatile у объекта, на который он показывает. Их бы надо как-то поженить между собой. Однако это невозможно, т.к. невыровненный доступ по указателю, помеченному __unaligned, вроде, и определен, но volatile накладывает свое "вето" на эту невыровненность, потому что иначе сломается семантика доступа к volatile. Т.е. компилятор должен тут решить, как ему поступать в данном случае: 1) "закрыть глаза" на строгую семантику доступа к volatile в части кол-ва обращений к объекту (при этом не оптимизировать сам доступ), разрешая таким образом работу с невыровненным указателем; 2) пытаться соблюсти корректный доступ к volatile-объекту, а это ничто иное как обеспечить однократный доступ к памяти инструкцией соответствующей разрядности доступа - а для этого нужно отбросить __unaligned и "задним числом" положиться на программиста, что указатель гарантированно выровнен. Если же юзер указатель не выровнил, то вылезет UB по отношению к volatile-объекту (ведь по отношению к обычному доступу UB уже "заранее" парирован ключевым словом __unaligned).

Судя по листингам, по первому пути пошел GCC, а по второму LLVM/CLang, который мне, в свою очередь, и кажется более правильным.
 

Цитата

насколько я понял оппонент ваш про маппинг имел ввиду как раз то что в заголовке темы - UB с указателями на невыровненные адреса при прямом маппинге структуры на буфер с данными без сериализации/десериализации

Вот если есть __unaligned или что-то подобное в компиляторе, то проблем нет. Напрямую "натягивать" указатель типа структуры на память может выйти боком при strict aliasing, но эта проблема решаема: в C++, например, с помощью placement new.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 10/22/2023 at 12:04 PM, Arlleex said:

Тогда с чего компилятор будет генерировать UB?

В прошлый раз (в теме, которую Вы указали) мы обсуждали не UB по выравниванию, а UB из-за доступа к volatile между двумя точками следования.

у вас какое-то странное понимание стандартов - для вас источник истинности это поведение компилятора а не указание стандарта, такой код не то что на другой архитектуре - на другом компиляторе не заработает

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, sasamy сказал:

у вас какое-то странное понимание стандартов - для вас источник истинности это поведение компилятора а не указание стандарта

И стандарт, и дополнения/исключения, описанные для конкретного компилятора - истина.
 

Цитата

такой код не то что на другой архитектуре - на другом компиляторе не заработает

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 10/22/2023 at 12:19 PM, Arlleex said:

дополнения/исключения, описанные для конкретного компилятора - истина.

нет, для С поведение определяет стандарт а не компилятор, это ведь ваши слова ?

Quote

Стандарт четко формулирует понятие UB, и на то оно UB, чтобы не гарантировать вообще ничего.

вот  вам и пример - вы пишете как вам вздумается и плевать вам на стандарт, для вас он только чтобы цитатами кому нибуть нагадить 🙂

 

Изменено пользователем sasamy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По-моему, Вам абсолютно все равно на смысл сообщений, Вы цитируете и скрещиваете вырванные из контекстов фрагменты и пытаетесь играть в детектива.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 10/22/2023 at 12:45 PM, Arlleex said:

Вы цитируете и скрещиваете вырванные из контекстов фрагменты

я специально даю ссылки чтобы не было претензий про вырванный контекст. Стандарт любо соблюдают либо нет независимо от контекста.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...