在没有访问任何数据的NULL指针上调用方法是否会失败?

Tys*_*obs 1 c++ methods null pointers

该计划是否:

#include <stdio.h>

struct foo
{
   void blah()  {printf("blah\n");}
   int i;
};

void main(int, char**)
{
   ((foo*)NULL)->blah();
}
Run Code Online (Sandbox Code Playgroud)

blah在你知道的任何编译器上崩溃,或者做输出以外的任何事情?当通过NULL指针调用时,任何函数是否会崩溃,如果它不访问任何成员(包括vtable)?

关于这个主题还有其他问题,例如在NULL指针上访问类成员,并且它是合法/定义良好的C++来调用不通过空指针访问成员的非静态方法吗?,并且总是指出这会导致未定义的行为.但这在现实世界中是不确定的,还是只在标准的世界中?现有的编译器是否表现不如预期?你能想到为什么未来的编译器不会按预期运行的任何合理的理由吗?

如果函数确实修改了成员,但是保护了NULL ptr.例如,

void foo::blah()
{
   foo* pThis = this ? this : new foo();
   pThis->i++;
}
Run Code Online (Sandbox Code Playgroud)

编辑:对于记录,我想要的原因是使我的链表类的接口尽可能简单明了.我想将列表初始化为NULL,其惯用用法如下:

pList = pList->Insert(elt);
pList = pList->Remove(elt);
...
Run Code Online (Sandbox Code Playgroud)

所有操作员返回新头元素的位置.不知怎的,我没有意识到使用容器类会让事情变得更容易,没有任何缺点.

Dav*_*eas 8

你能想到为什么未来的编译器不会按预期运行的任何合理的理由吗?

一个有用的编译器可能会添加代码来访问调试版本中的真实对象,以期帮助您在开发周期的早期代码中捕获此问题.

如果函数确实修改了成员,但是保护了NULL ptr.例如,

void foo::blah()
{
   foo* pThis = this ? this : new foo();
   pThis->i++;
}
Run Code Online (Sandbox Code Playgroud)

由于使用空指针调用该函数是未定义的行为,因此编译器可以假定测试将始终通过并优化该函数:

void foo::blah()
{
   this->i++;
}
Run Code Online (Sandbox Code Playgroud)

请注意,这是正确的,因为如果this不为空,它表现为,如果原来的代码被执行,如果this是零,这将是未定义行为,编译器不需要提供任何特定的行为的.

  • @TysonJacobs:特别是,请阅读:http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html (4认同)
  • @TysonJacobs:因为优化器看到的代码不是您编写的代码,但已经看到了各种编译通道,因此检查优化器看到的可能是也可能没有由程序员编写,或者可能是内联几个函数或其他任何东西 - 优化器唯一关心的是使代码运行得更快,符合标准规则. (2认同)

Mar*_*som 5

未定义的行为意味着您不能依赖将要发生的事情.但是,在调试时知道幕后发生的事情有时很有用,这样当不可能发生时你并不会感到惊讶.

大多数编译器会将其编码为带有隐藏this参数的简单函数,如果this从未引用参数,则代码将按预期工作.

检查this == NULL可能不起作用,具体取决于编译器优化的积极程度.由于一个格式良好的程序不可能具有this==NULL,编译器可以自由地假装它永远不会发生并if完全优化掉该语句.我知道微软的C++不会进行优化,因为它们的GetSafeHWND功能依赖于它按预期工作.

  • @TysonJacobs:语言律师不需要.`this`永远不会为null,所以任何不是'null`的检查都会传递.完全有效. (2认同)