Русский
Открыть в Telegram

Пост Ладно, искать баги в компиляторах весело, но недостаточно.

17 августа 2026
C
C++: Хроники Дурки🚑
Ссылка
нажмите — покажем
Ладно, искать баги в компиляторах весело, но недостаточно. Давайте поиграемся в чуть более интересные игры. Вспомним, что у нас в С++ есть правило: структура не может иметь нулевой размер. Потому что у ее инстанса должен быть адрес, и здесь С++ как-то забыл про Zero Cost и все такое. Зато С++ вспомнил про Zero Cost, когда мы примешиваем пустую структуру в наследование другой. struct Empty1 {}; struct Empty2 {}; struct NonEmpty { int Value; }; struct MyClass1 :public NonEmpty ,public Empty1 ,public Empty2 { }; struct MyClass2 :public Empty1 ,public NonEmpty ,public Empty2 { }; struct MyClass3 :public Empty1 ,public Empty2 ,public NonEmpty { }; static_assert(sizeof(NonEmpty) + sizeof(Empty1) + sizeof(Empty2) == 6); static_assert(sizeof(int) == 4); static_assert(sizeof(MyClass1) == 4); static_assert(sizeof(MyClass2) == 4); static_assert(sizeof(MyClass3) == 4); int main() {} Вот эта штука скомпилируется. Тоесть у нас структуры без размера имеют размер, но этот размер не добавляется к размеру общей структуры. Всвязи с чем я упоролся, и написал вот такой класс: struct Empty { void zero() { std::memset(this, 0, sizeof(*this)); } }; Свиду ничем не примечательный класс, который просто заполняет себя нулями. И это нормально работает для непустого класса, но пустой класс такими выкрутасами ломает соседние поля в классе, который его отнаследовал. struct CompressedPair : Empty { CompressedPair(Empty e, bool x) : Empty(e), b(x) { } bool b; }; int main() { auto a = CompressedPair({}, true); __builtin_printf("%b\n", a.b); a.zero(); __builtin_printf("%b\n", a.b); return 0; } Выводит 1 0 (да, да, это UB, я знаю, прекратите. Мы тут поржать собрались или где?) Но где-то тут в безумии зараждается идея... У нас же есть no_unique_address. А на gcc он кладет данные в padding других структур. #include <iostream> template <typename T> struct optional { union { char foo; T val; }; [[no_unique_address]] bool engaged; }; template <typename View> struct reverse_view { [[no_unique_address]] optional<typename View::iterator> cache; View base_; }; struct MyView { using iterator = int*; char begin_; }; int main() { std::cout << "sizeof = " << sizeof(reverse_view<MyView>) << std::endl; // clang - 24, gcc - 16 std::cout << "alignof = " << alignof(reverse_view<MyView>) << std::endl; } И тут я очень хотел развернуться мыслью, но быстро нашел уже закрытый баг с std::expected. (половина примеров выше взята из обсуждения этого бага, потому что они нагляднее чем то, с чем работал я). Если коротко, то методы expected могли зачищать переменные вокруг себя, если те оказывались в из padding. Потому что emplace пересоздавал внутренний объект целиком. Но, увы, примера воспроизводящего это дело у меня нет. А после этого примера все остальное рядом меркнет. Увы.
4 · 1.3K ·

Рядом в ленте

CC++: Хроники Дурки🚑Убедительная просьба - обновляйте компиляторы. Помимо внедрения множества способов выстрелить себе в ногу, новые версии компиляторов чинят разные веселые баги. CC++: Хроники Дурки🚑Ладно, разумеется прошлый пост был набросом. Никогда не обновляйте компиляторы без очень серьезных на то причин. Мало ли что там сломается, а у вас не будет ком
это сообщение
CC++: Хроники Дурки🚑#толькосвоимемы Код взят тут. if (dim == 0) idx_dim = i0; else if (dim == 1) idx_dim = i1; else if (dim == 2) idx_dim = i2; else if (dim == 3) idx_dim = i3; conCC++: Хроники Дурки🚑Если кто не знаком с библиотекой nlohmann/json - она прекрасна. Мои мысли о том, как должна выглядеть библиотека для пользователя, она начала формировать еще го

Открытая публичная лента из поискового индекса ChatCrawler — «Google по публичному Telegram»; обновляется по мере обхода площадки. Время — UTC.

Только публичный контент, официальный API Telegram. О проекте · Вопросы · Границы индекса · Убрать страницу из выдачи · Каталог · Поиск · Как мы считаем