Telegram Group Search
Попью кофе
#dev

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

Начнем с того, что есть нуль, а есть ноль. NULL не обязан иметь адрес 0 и, например, на некоторых архитектурах и интерпретаторах C это не так. Прагматичным людям из POSIX это не нравится, поэтому там NULL всегда имеет адрес 0. Впрочем, не обязательно даже уходить далеко в прошлое: amdgcn определяет NULL как -1, так что встретиться с таким сегодня вполне реально. Типичное определение NULL как (void*)0 на таких машинах все еще работает, потому что (void*)0 стандарт определяет равным NULL, но вот int x = 0; (void*)x портабельно NULL не даст.

Как вытекает из предыдущего, ничего особенного в адресе NULLа нет, и в железе никто не запрещает существовать странице по адресу 0. Железу плевать на то, какие правила накладывает стандарт C, и поэтому, например, на процессорах x86 в real mode по адресам 0256 хранятся таблицы прерываний. Разыменовывать адрес 0 в C все еще UB, но вот 1 разыменовать никто не запрещает.

Впрочем, одно дело — UB по стандарту, другое — поведение на практике. В прошлом стандарт C воспринимался скорее как гайдлайн, чем правила. Старые компиляторы не делали умных оптимизаций, и вообще Ритчи не подразумевал, что за счет UB будут оптимизировать, поэтому на многих платформах разыменование нулевого указателя только и делало, что читало значение в памяти по адресу 0. Компилятор C на HP-UX (это были еще те времена, когда свободных компиляторов C не было, и под каждую платформу были свои компиляторы, зачастую платные), например, давал опцию: мапать страницу по адресу 0, чтобы *(int*)NULL возвращало 0 (гарантированно! без современного понимания UB!), или не мапать, чтобы падало.

В современном мире писать по адресу, совпадающему с адресом NULL, опасно прям совсем. В embedded, где такое периодически приходится делать, у этой проблемы есть два решения: молоток и микроскоп. Во-первых, можно написать код для записи по адресу 0 на ассемблере, железо сожрет. Во-вторых, иногда железо игнорирует старшие биты адреса, поэтому можно записывать не по адресу 0, а, например, по адресу 0x80000000, который железо воспримет так же, а компилятор проинтерпретирует корректно.

Хочется верить, что по крайней мере на современных платформах разыменовывание NULL (если его не выкинет компилятор, конечно) приведет к сегфолту или чему-то подобному. Это не так. Во-первых, Linux поддерживает флаг personality MMAP_PAGE_ZERO, аллоцирующий страницу по адресу 0 на старте программы для совместимости с System V. Во-вторых, даже без этого вы можете с помощью mmap аллоцировать страницу по адресу 0 руками — этим даже пользовались эмуляторы.

Потом эту лавочку прикрыли, и даже не потому, что это скрывает баги в программах на C. Ну, точнее, ровно поэтому, только программой на C здесь выступает само ядро. Достаточно большое количество ядерных эксплоитов того времени заключалось в том, чтобы дата рейсом или иным методом заставить ядро разыменовать нулевой указатель. Поскольку внутри ядра (была) видна память текущего процесса, это приводило к тому, что пользовательская память начинала интерпретироваться как ядерные структуры. Чтобы этого избежать, сейчас Linux не позволяет аллоцировать страницы ниже адреса sysctl vm.mmap_min_addr — 64 кибибайта на большинстве устройств. (Нет бы писать без багов...)

На этом история с разыменованием нуля могла бы закончиться: в Windows ограничение на память на малых адресах было уже давно, в Linux ввели, других операционных систем не существует. Но хипстеры придумали WebAssembly, и поскольку с ним вопрос об изоляции внутри контейнера не встает, по адресу 0 здесь вполне есть доступная память. Некоторых это бесит, некоторых удивляет, меня — радует, ибо нефиг проталкивать ограничения уровней абстракции вниз (впрочем, с этим в WebAssembly проиграли в других местах).

Такие дела.
Хогвартс мой, где же твоя выручай комната?
Набросайте нам идей проектов на сиспрошный хакатон!

А заодно подписывайтесь на канал сиспро, там и мемы про системщину и математику будут, спасибо @bsielwk)
Уже через неделю пройдет первое в этом семестре сиспрошное мероприятие Хакатон!
Это событие, когда мы дружно запираемся в офисе, разбиваемся по командам, выбираем тему для проекта и весь день кодим в свое удовольствие!

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

Как это прошло в том году, можете посмотреть здесь: https://youtu.be/V886KappFwA?si=_qp9LRIYygubNmar

А в комментариях к этому посту можете поделиться своими идеями для проекта на хакатон! Может, именно ваша идея принесет какой-то из наших команд победу в этом году!
Чем хороши воскресенья: в них нет созвонов => можно и код пописать 😏
Аааа, семестр начинается через 10 минут!

И какой семестр: начинается третий сезон алгосов и второй сезон плюсов на английском! Будет жарко.
В трениках в ректорат, еее



Какую же безумную уверенность в себе дает этот костюм!
This media is not supported in your browser
VIEW IN TELEGRAM
Так, а как работать после 4 пар в универе с утра?
Хуйня эти ваши speaking clubs, хотите прогрессировать, попробуйте прочитать семестр лекций по плюсам на английском.
Обычная пара по плюсам в этом семестре
Сегодня работаю тропинкоукладчиком 🫡
Искал одну старую картинку (вот эту, помните эту историю про Мэтта Тейлора и его рубашку, да?), случайно увидел свои посты 2012 года... ну я, конечно, тогда был прям агрессивно тупым. Надо как-то законодательно запретить читать свои старые посты, чтобы не расстраиваться.

Хотя с пары постов и картинок я даже посмеялся, неплохо, уже тогда были все задатки твиттерского.
а попался он из-за того, что постил свои треки в страве!
Вообще-то два года
2025/02/05 20:51:52
Back to Top
HTML Embed Code: