Обновить

Комментарии 11

эта программа у меня стабильно падает где-то за 7-10млн итераций чтения

У меня она стабильно сразу выдаёт

Bus error (core dumped)

Ваша x86 архитектура позволяет слишком много вольностей )

PS -fsanitize=undefined явно детектит проблему и в gcc и в clang.

а в режиме бин трансляции если таргет платформа была x86 что будет?

емнип, ошибку при невыровненном чтении на x86 тоже можно получить, если в какую-нибудь avx инструкцию, требующую выравнивание, подать невыровненный адрес

А так, да - дебажить bus-error проще чем что-то стреляющее с такой малой вероятностью (и космические лучи обвинишь, ища разгадку или репродьюс)

а в режиме бин трансляции

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

Да, SIMD на x86 часто требует выравнивания (хотя есть, скажем, movups).

дебажить bus-error проще

Согласен. Но санитайзер тоже порадовал, надо бы почаще использовать...

ubsan ловит, да

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

но мысли сделать хотя бы "раз в неделю" запуски приходят

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

Есть бит RFLAGS.AC, который вызывает исключение #AC при невыравненном доступе. Им пользоваться невозможно, потому что почти все компиляторы (не только C) генерируют код, нарушающий это правило.

В сравнительно новых интеловских процессорах появился MSR_MEMORY_CTRL.SPLIT_LOCK_DISABLE, разрешение которого приводит к #AC при невыравненных locked доступах.

В вашем примере это бы сработало из-за иначе ненужного seq-cst режима. Если бы использовался relaxed или acq/rel, то на x86 они обычно моделируются простыми load и store, и split lock detection бы не сработал.

P.S. Явление называется 'torn writes' и в дикой природе встречается начиная с Core2 (~2008 г).

Генерируемый асемблер в годболте приложенном не меняется при смене мемори ордеров

Для load'ов да, plain load будет seq-cst если store с lock-префиксом. gcc генерирует XCHG для записи, эта инструкция с неявным префиксом lock.

Но собственно, это ничего в моем ответе не меняет.

а malloc <...> этого не делают

Делает. Он возвращает всегда максимально выровненный указатель.

Спасибо за уточнение. Добавил апдейт в текст

"Максимально" это конечно перегиб, всё же malloc гарантированно выровнен по выравниванию наиболее выровненного встроенного сишного типа (обычно выровнен в два машинных слова), чего просто атомикам, конечно, и хватит, но всё же для гарантий в более общем случае лучше использовать aligned_alloc, например при выравнивании по ширине кеш-линии, как иногда делается

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации