为什么没有方法查找的段错误

时间:2013-10-16 17:01:06

标签: c++ pointers null segmentation-fault

我正在寻找有关这段代码的澄清。对A :: hello()的调用有效(我期望一个segv)。 segfault确实通过对成员x的访问,所以看起来单独的方法解决方案实际上并没有解除引用bla?

我编译了优化关闭,gcc 4.6.3。为什么bla-> hello()不会爆炸?只是想知道'发生了什么事。感谢。

class A
{

public:
    int x;

    A() { cout << "constructing a" << endl; }

    void hello()
    {
        cout << "hello a"  << endl;
    }

};

int main()
{
    A * bla;
    bla = NULL;
    bla->hello();    // prints "hello a"
    bla->x = 5;      // segfault
}

5 个答案:

答案 0 :(得分:5)

您的程序显示未定义的行为。 “似乎工作”是未定义行为的一种可能表现。

特别是,bla->hello()调用似乎有效,因为hello()实际上并没有以任何方式使用this,所以它恰好没有注意到this不是一个有效的指针。

答案 1 :(得分:3)

您正在取消引用NULL指针,即尝试访问存储在地址NULL的对象:

bla = NULL;
bla->hello();
bla->x = 5;

导致 未定义的行为 ,这意味着在向成员5分配x时会发生任何事情,包括seg错误在调用hello方法时,还包括欺骗性“按预期工作”效果。

答案 2 :(得分:2)

理论上讲,这是未定义的行为。实际上,在调用this时不使用hello()指针,它根本不引用您的类,因此可以工作并且不会产生内存访问冲突。但是,当您执行bla->x时,您试图通过未初始化的bla指针引用内存,并且它会崩溃。同样,即使在这种情况下,也不能保证它会崩溃,这是未定义的行为。

答案 3 :(得分:1)

只要成员函数没有取消引用this,调用它通常是“安全的”,但是你处于未定义的行为

答案 4 :(得分:1)

至少在典型的实现中,当您通过指针调用非虚拟成员函数时,该指针不会被解引用以找到该函数。

指针的类型用于确定搜索函数名称的范围(上下文),但这完全在编译时发生。指针指向的内容(包括“无”,在空指针的情况下)与查找函数本身无关。

在编译器找到正确的函数后,它通常会将a->b(c);之类的调用转换为大致相当于:b(a, c); - a的调用,然后变为this的值在功能里面。当函数引用对象中的数据时,this被取消引用以找到正确的对象,然后通常应用偏移量来查找该对象中的正确项。

如果成员函数从不尝试使用任何对象的成员,this是空指针的事实不会影响任何事情。

另一方面,如果成员函数确实尝试使用该对象的成员,它将尝试取消引用this来执行该操作,并且如果this是NULL指针,这是行不通的。同样,调用虚函数总是使用对象中的vtable指针,因此尝试通过空指针调用虚函数可能会失败(无论虚函数中的代码是否引用对象中的数据)或不)。

正如我先说的那样,我在谈论这里的典型实现。从标准的角度来看,您只是具有未定义的行为,这就是它的结束。从理论上讲,实现不会 按照我所描述的方式工作。然而,实际上,基本上所有相当流行的C ++实现(例如,MS VC ++,g ++,Clang和Intel)在这些方面都非常相似。