美文网首页
C++ 虚函数调用崩溃问题分析

C++ 虚函数调用崩溃问题分析

作者: Strong_Liu | 来源:发表于2017-08-17 22:48 被阅读45次

最近帮同事排查了一个崩溃问题,用他的话说是一个「神奇的」崩溃问题。

这个问题大概是这样的。
同事在 A 类写了一个函数 doSomething,然后在某个地方调用。
代码简化如下:

class A
{
public:
    void doSomething()
    {
        printf("class A doSomething! \n");
    }
};

A *a;
a->doSomething();

是的,一切正常。

然后由于 A 类是基类,而这个函数其他子类可能需要重载实现。于是,就加上了 virtual 关键字,看样子一切正常。

class A
{
public:
    virtual void doSomething()
    {
        printf("class A doSomething! \n");
    }
};

A *a;
a->doSomething();

「神奇的」事情发生了,程序崩溃在了调用 doSomething 的地方。

同事陷入了深深的迷茫中。。。

经过一番 debug,真想终于水落石出。原因是对象 a 在调用 doSomething 的时候已经被其他地方赋为了空指针。

既然 a 是空指针,那么为什么不加 virtual 关键字的时候,调用 doSomething 就一切正常呢?

这是因为:

  • 在 C++ 里,非虚函数的地址是在编译\链接完成时就已经确定了。因此当运行到 a->doSomething() 这句时,是可以找到该函数地址,从而执行相应代码的。但是需要注意的是,不能在这个函数里使用 A 的成员变量,因为 this 指针的地址是非法的。

  • 而虚函数一般是通过虚函数表来实现的,在这个表中存的主要就是该类的虚函数的地址。虚函数表的创建是在对象实例化时完成的,也就是说虚函数的地址是在程序运行时才能确定。因此当运行到 a->doSomething() 这句时,由于 doSomething 是虚函数,而此时 a 对象又为空,用 a 去访问虚函数表必然引起非法访问,从而导致程序崩溃。


(完)

相关文章

网友评论

      本文标题:C++ 虚函数调用崩溃问题分析

      本文链接:https://www.haomeiwen.com/subject/eronrxtx.html