可访问空指针[重复]

Posted

技术标签:

【中文标题】可访问空指针[重复]【英文标题】:Null pointer accessible [duplicate] 【发布时间】:2014-04-10 12:40:35 【问题描述】:

我想知道为什么下面的小程序不会导致 NullPointerException。 有任何想法吗? 输出是 2x Hello World!!!在我的 macbook 上使用 clang-500.2.79。

#include <iostream>

using namespace std;

class Strange 
public:
    Strange() 
    virtual ~Strange() 
    void sayHello() 
        cout<<endl<<"Hello World!!!"<<endl;
    

;

int main(void) 
    Strange* s = new Strange();
    delete s; s = NULL;
    s->sayHello();
    (*s).sayHello();
    return 0;

【问题讨论】:

【参考方案1】:

C++ 没有“NullPointerException”。取消引用空指针只是未定义的行为,任何事情都可能发生。

在您的情况下,sayHello() 根本不访问*this,因此它恰好“正常”工作(在您的编译器、优化设置、运行时和硬件上)。但这并不能保证。未定义的行为只是未定义的;该程序也可以崩溃或在线订购披萨。

【讨论】:

感谢您的回答。因此,在将指针设置为 NULL 后,我有未定义的行为。如果我不将指针设置为 NULL 我有一个悬空指针,对吗?哪个也有某种未定义的行为,可能会更糟......那么我怎样才能避免这种未定义的行为呢? @user3392371 将指针设置为 null 不是 UB。 取消引用 这样的指针是 UB(就像取消引用一个未初始化的或其他悬空指针一样)。解决方案取决于您的情况:如果指针可以为空,请在使用前对其进行测试:if (s) s-&gt;sayHello();。如果指针非空是代码的先决条件,请将其记录为相应地调用它(即确保指针实际不为空)。在这种情况下,您也可以assert() 告知它不为空,这将在调试版本中为您提供错误检查。【参考方案2】:

我想知道为什么下面这个小程序不会导致 NullPointerException。

因为它是 C++,而不是“托管”语言,需要对每个操作进行昂贵的运行时检查。如果取消引用空指针,则不会出现异常;你会得到某种未定义的行为。

在这种情况下,成员函数不会访问对象,因此(在大多数实现中)它的行为就像指针是有效的一样。如果它确实访问了对象,那么您可能会遇到运行时错误或内存损坏,从而导致细微的错误和不眠之夜。

尽可能避免使用指针和new;必要时使用智能指针和其他RAII 技术。如果指针有可能为空,请在取消引用之前检查它。

【讨论】:

不太正确...我预计 NULL 取消引用会出现分段错误。但是,我确实认为编译器优化只是忽略了取消引用操作,因为该函数不使用 this 参数,因此不会发生实际的取消引用。 @immortal:仅当内存被访问时,且仅当指针指向不可访问的内存页时,且仅当硬件支持内存保护时。分段错误是硬件级别的错误,仅由实际访问内存的尝试触发;它对取消引用等软件级概念一无所知。 我尝试了一些编译器优化,并且现在还尝试了最新的 gcc(从 -O0 到 O3)并且输出始终有效,我从未遇到任何 seg 错误或其他异常:( @user3392371:确实;如果您实际上尝试通过指针访问内存,您只会得到段错误,无论优化级别如何,您的代码都不会这样做。它只是将空指针作为this 传递给函数,然后忽略它。如果你创建函数virtual,或者添加一个成员变量并在函数中读取或写入它,那么你可能会遇到错误。更好的是:首先避免未定义的行为。 感谢您的解释!所以它工作的原因是成员函数没有访问对象。有了这些信息,我就可以继续玩了……谢谢!!!

以上是关于可访问空指针[重复]的主要内容,如果未能解决你的问题,请参考以下文章

我以外的其他机器上的空指针异常[重复]

删除空指针[重复]

weblogic web应用启动后访问某个action空指针错误

onCreate空指针异常[重复]

getApplicationContext给出空指针异常[重复]

操作栏中的空指针异常[重复]