Нулевой указатель — Null pointer
В вычислении , указатель NULL или пустая ссылка является сохраненным значением для указания , что указатель или ссылка не относится к действительному объекту . Программы обычно используют нулевые указатели для представления таких условий, как конец списка неизвестной длины или невозможность выполнить какое-либо действие; это использование нулевых указателей можно сравнить с типами, допускающими значение NULL, и со значением Nothing в типе параметра .
Нулевой указатель не следует путать с неинициализированным указателем : нулевой указатель гарантированно не равен любому указателю, указывающему на действительный объект. Однако, в зависимости от языка и реализации, неинициализированный указатель может не иметь такой гарантии. Он может сравниваться с другими действительными указателями; или он может сравнивать равные нулевые указатели. И то и другое могло происходить в разное время; или сравнение может быть неопределенным .
СОДЕРЖАНИЕ
В C два нулевых указателя любого типа гарантированно сравниваются как равные. Макрос препроцессора NULL определяется как определяемая реализацией константа нулевого указателя, которая в C99 может быть переносимо выражена как ((void *)0) означающая, что целочисленное значение 0 преобразовано в тип void* (указатель на void ). Стандарт C не говорит, что нулевой указатель совпадает с указателем на адрес памяти 0, хотя на практике это может иметь место. Разыменование нулевого указателя является неопределенным поведением в C, и соответствующая реализация может предполагать, что любой указатель, для которого разыменован, не является нулевым.
На практике разыменование нулевого указателя может привести к попытке чтения или записи из памяти, которая не отображается, вызывая ошибку сегментации или нарушение доступа к памяти. Это может проявляться как сбой программы или трансформироваться в исключение программного обеспечения, которое может быть обнаружено программным кодом. Однако есть определенные обстоятельства, когда это не так. Например, в реальном режиме x86 адрес доступен для чтения и обычно для записи, и разыменование указателя на этот адрес является вполне допустимым, но обычно нежелательным действием, которое может привести к неопределенному, но не вызывающему сбоев поведению приложения. Бывают случаи, когда разыменование указателя на нулевой адрес является преднамеренным и четко определенным; например, код BIOS, написанный на C для 16-битных устройств x86 реального режима, может записывать IDT по физическому адресу 0 машины путем разыменования нулевого указателя для записи. Компилятор также может оптимизировать разыменование нулевого указателя, избегая ошибки сегментации, но вызывая другое нежелательное поведение . 0000:0000
В C ++, хотя NULL макрос был унаследован от C, целочисленный литерал для нуля традиционно предпочитался представлять константу нулевого указателя. Однако в C ++ 11 nullptr вместо нее используется явная константа нулевого указателя .
Другие языки
В некоторых средах языков программирования (по крайней мере, в одной проприетарной реализации Lisp, например) значение, используемое в качестве нулевого указателя (вызываемого nil в Lisp ), может фактически быть указателем на блок внутренних данных, полезных для реализации (но не доступный явно из пользовательские программы), что позволяет использовать один и тот же регистр в качестве полезной константы и быстрого доступа к внутренним компонентам реализации. Это известно как nil вектор .
В языках с тегированной архитектурой возможно нулевой указатель может быть заменен тегированным объединением, которое обеспечивает явную обработку исключительного случая; фактически, возможно, нулевой указатель можно рассматривать как помеченный указатель с вычисляемым тегом.
В языках программирования для нулевого указателя используются разные литералы . В Python, например, вызывается нулевое значение None . В Pascal и Swift вызывается нулевой указатель nil . В Eiffel это называется void ссылкой.
Нулевое разыменование
Поскольку нулевой указатель не указывает на значимый объект, попытка разыменования (т. Е. Доступа к данным, хранящимся в этой ячейке памяти) нулевого указателя обычно (но не всегда) вызывает ошибку времени выполнения или немедленный сбой программы.
- В C разыменование нулевого указателя является неопределенным поведением . Многие реализации приводят к тому, что такой код приводит к остановке программы с нарушением доступа , потому что представление нулевого указателя выбирается как адрес, который никогда не выделяется системой для хранения объектов. Однако такое поведение не универсально. Это также не гарантируется, поскольку компиляторам разрешено оптимизировать программы в предположении, что они свободны от неопределенного поведения.
- В Delphi и многих других реализациях Паскаля константа nil представляет собой нулевой указатель на первый адрес в памяти, который также используется для инициализации управляемых переменных. Разыменование его вызывает внешнее исключение ОС, которое отображается на экземпляр исключения Pascal EAccessViolation, если модуль System.SysUtils связан в предложении uses.
- В Java доступ к нулевой ссылке запускает NullPointerException (NPE), который может быть обнаружен кодом обработки ошибок, но предпочтительной практикой является обеспечение того, чтобы такие исключения никогда не возникали.
- В .NET доступ к нулевой ссылке вызывает исключение NullReferenceException. Хотя их перехват обычно считается плохой практикой, этот тип исключения может быть перехвачен и обработан программой.
- В Objective-C сообщения могут быть отправлены nil объекту (который является нулевым указателем), не вызывая прерывания программы; сообщение просто игнорируется, а возвращаемое значение (если есть) — nil или 0 , в зависимости от типа.
- До появления SMAP ошибка разыменования нулевого указателя могла быть использована путем сопоставления нуля страницы с адресным пространством злоумышленника и, следовательно, заставления нулевого указателя указывать на эту область. В некоторых случаях это могло привести к выполнению кода .
Смягчение
Существуют методы, облегчающие отладку разыменования нулевого указателя. Бонд и др. предлагаем изменить JVM, чтобы отслеживать нулевое распространение. Идея системы Casper заключается в использовании преобразования исходного кода для отслеживания этого распространения без изменения JVM. В некоторых случаях можно автоматически сгенерировать патч для исправления исключений с нулевым указателем.
История
В 2009 году сэр Тони Хоара заявил , что он изобрел ссылку нулевой в 1965 году как часть Алгол W языка. В этой ссылке 2009 года Хоар описывает свое изобретение как «ошибку на миллиард долларов»:
Я называю это своей ошибкой на миллиард долларов. Это было изобретение нулевой ссылки в 1965 году. В то время я проектировал первую всеобъемлющую систему типов для ссылок на объектно-ориентированном языке (АЛГОЛ W). Моя цель состояла в том, чтобы гарантировать, что любое использование ссылок должно быть абсолютно безопасным, с автоматической проверкой компилятором. Но я не мог устоять перед соблазном вставить пустую ссылку просто потому, что это было так легко реализовать. Это привело к бесчисленным ошибкам, уязвимостям и системным сбоям, которые, вероятно, причинили боль и ущерб на миллиард долларов за последние сорок лет.
Нулевая ссылка
Не могу утверждать, но смею предположить, что нулевая ссылка это та, которая не передает ссылочной массы.
лол, читайте вопрос ТС. Сабж — тема.
сабж это ссылка с нулевого сайта, в теории не передающяя много веса. А на деле она полезнее чем сайты с пузомерками, ибо на нее еще не успели повесить кучу фильтров;)
Проще говоря, суть выраженная в названии топика или ещё чего-либо.
Некоторые подразумевают по нулевыми ссылками «рекламный текстовый блок с описанием сайта, размещаемый на первых позициях в категориях каталога».
Ещё могут нулевой ссылкой называть линк с сайта с тиц меньше 10.
Ссылка с сайта с нулёвыми параметрами. Очень полезна для вывода в ТОП по каким-то словам. Если взрослеющий сайт получит хорошую трастовость (на него сошлются другие трастовые сайты), то нулёвая ссылка превратится просто в хорошую. А если получится тИЦ0,PR1, то значит ссылка станет ссылкой с обычного сайтика, которая перестанет быть эффективной или даже станет бесполезной, если донор попадёт под фильтры.
Возможна ли нулевая ссылка?
Действителен ли этот фрагмент кода (и определено ли поведение)?
И g ++, и clang ++ компилируют его без предупреждения, даже при использовании -Wall , -Wextra , -std=c++98 , -pedantic , -Weffc++ .
Конечно, ссылка на самом деле не является нулевой, поскольку к ней нельзя получить доступ (это будет означать разыменование нулевого указателя), но мы могли бы проверить, является ли он нулевым, проверив его адрес:
4 ответа
Ссылки — это не указатели.
Ссылка должна быть инициализирована для ссылки на действительный объект или функцию. [Примечание: в частности, пустая ссылка не может существовать в четко определенной программе, потому что единственный способ создать такую ссылку — это привязать ее к «объекту», полученному путем разыменования нулевого указателя, что вызывает неопределенное поведение. Как описано в 9.6, ссылку нельзя напрямую привязать к битовому полю. ]
Некоторые другие операции описаны в этом международном стандарте как неопределенные (например, эффект разыменования нулевого указателя)
Как говорит Йоханнес в удаленном ответе, есть некоторые сомнения в том, следует ли категорически утверждать, что «разыменование нулевого указателя» является неопределенным поведением. Но это не один из случаев, вызывающих сомнения, поскольку нулевой указатель определенно не указывает на «действительный объект или функцию», и в комитете по стандартам нет желания вводить пустые ссылки.
Ответ зависит от вашей точки зрения:
Если вы судите по стандарту C ++, вы не можете получить нулевую ссылку, потому что сначала вы получаете неопределенное поведение. После этого первого случая неопределенного поведения стандарт позволяет случиться чему угодно. Итак, если вы напишете *(int*)0 , у вас уже будет неопределенное поведение, как и с точки зрения стандарта языка, разыменование нулевого указателя. Остальная часть программы не имеет значения, как только это выражение выполнено, вы выбываете из игры.
Однако на практике пустые ссылки можно легко создать из нулевых указателей, и вы не заметите этого, пока не попытаетесь получить доступ к значению, стоящему за нулевой ссылкой. Ваш пример может быть слишком простым, так как любой хороший оптимизирующий компилятор увидит неопределенное поведение и просто оптимизирует все, что от него зависит (нулевая ссылка даже не будет создана, она будет оптимизирована).
Тем не менее, эта оптимизация зависит от компилятора, чтобы доказать неопределенное поведение, что может быть невозможно. Рассмотрим эту простую функцию внутри файла converter.cpp :
Когда компилятор видит эту функцию, он не знает, является ли указатель нулевым указателем или нет. Таким образом, он просто генерирует код, который превращает любой указатель в соответствующую ссылку. (Кстати: это пустяк, поскольку указатели и ссылки — это одно и то же в ассемблере.) Теперь, если у вас есть другой файл user.cpp с кодом
Компилятор не знает, что toReference() разыменует переданный указатель, и предполагает, что он возвращает действительную ссылку, которая на практике оказывается пустой ссылкой. Вызов завершается успешно, но при попытке использовать ссылку программа вылетает. С надеждой. Стандарт допускает все, что угодно, в том числе появление розовых слонов.
Вы можете спросить, почему это актуально, ведь неопределенное поведение уже было запущено внутри toReference() . Ответ — отладка: пустые ссылки могут распространяться и размножаться так же, как и нулевые указатели. Если вы не знаете, что могут существовать пустые ссылки, и научились избегать их создания, вы можете потратить некоторое время, пытаясь выяснить, почему ваша функция-член дает сбой, когда она просто пытается прочитать простой старый член int . (ответ: экземпляр в вызове члена был пустой ссылкой, поэтому this является нулевым указателем, и ваш член вычисляется как адрес 8).
Так как насчет проверки нулевых ссылок? Вы дали линию
В вашем вопросе. Что ж, это не сработает: согласно стандарту у вас будет неопределенное поведение, если вы разыменовываете нулевой указатель, и вы не можете создать нулевую ссылку без разыменования нулевого указателя, поэтому нулевые ссылки существуют только внутри области неопределенного поведения. Поскольку ваш компилятор может предполагать, что вы не запускаете неопределенное поведение, он может предполагать, что не существует такой вещи, как пустая ссылка (даже если он легко выдаст код, который генерирует пустые ссылки!). Таким образом, он видит условие if() , делает вывод, что оно не может быть истинным, и просто отбрасывает весь оператор if() . С введением оптимизации времени компоновки стало просто невозможно надежно проверять нулевые ссылки.
TL; DR:
Нулевые ссылки — это своего рода ужасное существование:
Их существование кажется невозможным (= по стандарту),
но они существуют (= сгенерированным машинным кодом),
но вы не можете их видеть, если они существуют (= ваши попытки будут оптимизированы),
но они все равно могут убить вас, не подозревая (= ваша программа вылетает в странных точках или хуже).
Ваша единственная надежда состоит в том, что их не существует (= напишите свою программу, чтобы не создавать их).
Разные способы сделать нулевую ссылку?
Есть ли способ сделать нулевую ссылку, помимо этих методов?
Я не возражаю против того, что страница переместится вверх, но я не хочу, чтобы она меняла URL-адрес в адресной строке. Идеальная ссылка была бы максимально похожа на те, которые были показаны на навигационных блоках в Википедии, но есть гораздо больше, чем кажется на первый взгляд, так как у нее довольно большой скрипт, связанный с ней. Я просто смотрю на то, чтобы положить в a тега.
5 ответов
Вам просто нужно что-то, что вы можете вставить в тег <a> ? ОК:
Объедините его с любым из методов href= из вашего вопроса.
Учитывая, что ссылка, которая не идет никуда, довольно бесполезна, могу ли я предположить, что вы хотите запустить функцию JavaScript при нажатии ссылки? Если да, сделайте следующее:
Метод # является самым простым и всегда совместим. Однако использование href= # переместится в начало страницы. Чтобы предотвратить скачок, просто укажите неназванный якорь. Как это:
В Википедии используется третий вариант. Чтобы использовать это, вы можете использовать этот HTML-код:
Затем присоедините обработчик событий с помощью JavaScript:
addEventListener должен работать в большинстве современных браузеров, но чтобы быть более совместимым и более кратким, вы можете использовать библиотеку JavaScript, такую как jQuery:
Нет, все потенциально допустимые альтернативы не выполняются ИМО. Я сделал следующие эксперименты с Chrome и Firefox, сумев выделить 2 дополнительных альтернативы тем, которые уже были предложены в вопросе и ответах.
Те, которые провалились (НЕ пустые ссылки):
Этот файл не отображается как ссылка вообще, и он не доступен для просмотра.
Следующая альтернатива при щелчке переместилась в начало документа — не пустая ссылка.
Следующая альтернатива при щелчке перемещается в сторону от документа, а не нулевой.
Следующая альтернатива при нажатии, при нажатии, переходит к началу документа — не к нулевой ссылке.
Теперь вот те, которые работали: True Null Links:
Обе альтернативы ниже, при нажатии, ничего не делают — нулевые ссылки? ДА.
Этот другой почти такой же, как и выше, но предлагается в качестве истинной альтернативы, в основном для ее краткости.
ПРИМЕЧАНИЕ. Одним из ключевых различий между моими рабочими решениями и решениями nnnnnn является то, что я предпочитаю пустой href , иначе они работают по тому же принципу.