Какая часть разыменования указателей NULL вызывает нежелательное поведение? - PullRequest
2 голосов
/ 10 июля 2009

Мне интересно, какая часть разыменования NULL ptr вызывает нежелательное поведение. Пример:

//  #1
someObj * a;
a = NULL;
(*a).somefunc();   // crash, dereferenced a null ptr and called one of its function
                   // same as a->somefunc();

//  #2
someObj * b;
anotherObj * c;
b = NULL;
c->anotherfunc(*b);   // dereferenced the ptr, but didn't call one of it's functions

Здесь в # 2 мы видим, что я на самом деле не пытался получить доступ к данным или функции из b, так что это все равно будет вызывать нежелательное поведение, если * b просто преобразуется в NULL, и мы передаем NULL в anotherfunc ()

Ответы [ 16 ]

0 голосов
/ 10 июля 2009

Хотя в стандартах разыменование нулевого указателя (NULL) является неопределенным поведением, текущие процессоры и операционные системы генерируют ошибку сегментации или аналогичную ошибку.

Может быть, та функция, которую вы вызвали, принимает ссылочный параметр (который является указателем), и эта функция не использует параметр, поэтому значение NULL не будет разыменовано.

0 голосов
/ 10 июля 2009

Вы блуждаете по неопределенным территориям.

Вы можете думать о вызове функции-члена, как о вызове обычной функции с дополнительным, неявным аргументом this указателя.Сам вызов функции просто помещает аргументы на место в соответствии с соглашением о вызовах и переходит на адрес памяти.

Так что простой вызов функции-члена по указателю объекта NULL не обязательно вызывает сбой (если только это невиртуальная функция).Вы получаете недопустимый сбой доступа к памяти только при попытке доступа к переменным-членам объекта или vtable.

В случае # 2 вы можете получить или не получить немедленный сбой в зависимости от того, как объявлено anotherfunc.Если значение равно someObj, то вы косвенно обращаетесь к NULL в самом вызове функции, что приводит к сбою.Если для ссылки требуется someObj, то обычно ничего не происходит, поскольку ссылки реализуются с использованием указателей под капотом, а фактическое косвенное обращение откладывается до тех пор, пока вы не попытаетесь получить доступ к данным элемента.

0 голосов
/ 10 июля 2009

Это все равно вызовет сбой, потому что вы все еще указываете компилятору попытаться получить доступ к памяти в местоположении 0 (что запрещено). В зависимости от подписи anotherfunc вы можете передавать ссылку (которую запрещено инициализировать нулевым объектом) или копию из *b.

0 голосов
/ 10 июля 2009

NULL равно 0. Поскольку 0 не указывает на реальный адрес памяти, вы не можете разыменовать его. * b не может просто преобразовать в NULL, поскольку NULL - это то, что относится к указателям, а не к объектам.

0 голосов
/ 10 июля 2009

вам нужно больше узнать о anotherfunc (), чтобы сказать, что произойдет, если вы передадите его null. это может быть хорошо, это может произойти сбой, зависит от кода.

0 голосов
/ 10 июля 2009

Разыменование нулевого указателя - неопределенное поведение.

Не гарантируется сбой, и вы ничего не гарантируете при этом. Ибо все, что вы знаете, кто-то где-нибудь в мире будет бить каждый раз, когда вы это делаете. Это правильное поведение, поскольку оно не определено.

Также ваши указатели не могут быть инициализированы как NULL, поэтому, если вы хотите, чтобы они были точно NULL, вам следует явно установить их в NULL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...