В любой современной системе для таких целей можно просто использовать значения указателя 1
, 2
, ... 4095
. Другим частым выбором является (uintptr_t)-1
, который технически хуже, но, тем не менее, используется чаще, чем 1
.
Почему эти значения "безопасны"?
Современные системы защищают от обращения к указателю NULL, делая невозможным сопоставление чего-либо с нулевым виртуальным адресом. Почти любое разыменование указателя NULL приведет к попаданию в эту несуществующую область, и аппаратное обеспечение сообщит системе ОС, что произошло что-то плохое, что приведет к тому, что ОС выполнит сегментацию процесса.
Поскольку страницы виртуальной памяти выровнены по страницам (не менее 4 КБ текущее оборудование), и ничего не отображается на нулевой адрес, ничто не может быть отображено на весь диапазон 0, ..., 4095
, защищая все эти адреса одинаково, и вы можете использовать их как значения специального назначения.
Сколько места виртуальной памяти зарезервировано для этой цели, является системным параметром, в linux он управляется /proc/sys/vm/mmap_min_addr
, и пользователь root может изменить его на ноль, что отключит эту защиту (что было бы не очень умной идеей). По умолчанию в Ubuntu — 64 КБ (т. е. 16 страниц).
По этой же причине (uintptr_1)-1
менее безопасен, чем 1
; хотя любая загрузка более чем одного байта приведет к нулевой странице, сам адрес (uintptr_1)-1
не обязательно защищен таким образом. Следовательно, выполнение строковых операций над (char*)-1
не обязательно приводит к ошибке сегментации.
Редактировать:
Мое первоначальное объяснение со специальным сопоставлением кажется немного устаревшим, возможно, так дела обрабатывались на старой платформе Mac/PPC. Несмотря на то, что эффект почти такой же, я изменил детали ответа, чтобы отразить современный Linux. В любом случае, важным моментом является не как защита от нулевых страниц, а то, что любая нормальная современная система будет иметь некоторую защиту от нулевых страниц, которая охватывает по крайней мере указанный диапазон адресов. Более подробную информацию можно найти в этом ответе SO: https://stackoverflow.com/a/12645890/2445184
person
cmaster - reinstate monica
schedule
21.12.2013
struct { int type; union { char *string_value; double float_value; } }
- person   schedule 21.12.2013'\0'
) потребует еще одного целочисленного поля. - person nullptr   schedule 21.12.2013static const string invalid_string;
. Вы можете сравнить адрес любой строки с адресом этого объекта и разыменовать его без сбоев. Обратите внимание, что сбой иногда является хорошим и желательным поведением, но это зависит от того, чего вы хотите. Если вы считаете доступ к зарезервированному узлу программной ошибкой, она действительно должна рухнуть. - person Damon   schedule 21.12.2013