空指针也不崩溃-转载

http://blog.sina.com.cn/s/blog_532f6e8f01017ljb.html

 

class A

{

public:

int m_iA1;

void print()

{

cout << "A" << endl;

}

};

int main()

{

A *pObjectA=NULL;

pObjectA->print();

return 0; 

}

 

*a没有初始化,结果成功输出“A”。

分析:成员函数在代码段,成员变量在数据段,地址为在类对象地址基础上累加。

此处的print成员函数没有用到成员变量,与类外独立函数无异。调用的时候不涉及数据段,不会崩溃。

 

如果成员函数print中使用到了成员变量,情况会是怎样呢?

class A

{

public:

int m_iA1;

char m_chA2;

void print()

{

m_iA1 = 1;

cout << "A" << endl;

}

};

int main()

{

A *pObjectA=NULL;

pObjectA->print();

return 0; 

}

编译执行后,崩在了print函数中的红色标记语句。

分析:此处的print成员函数用到成员变量m_iA1,我们可以看到,&pObjectA=0x00000000,&m_iA1=0x00000000,&m_iA2=0x00000004

空指针也不崩溃
访问了非法地址,崩溃了

 

尝试给pObjectA分配空间后,&pObjectA=0x003b6060,&m_iA1=0x003b6060,&m_iA2=0x003b6064,

空指针也不崩溃

这是合法的数据段地址,访问成功。

 

我们再给A类加一点有趣的东西来验证一下

1、static静态变量

class A

{

public:

static int m_iSA4;

static void print()

{

m_iSA4 = 4;

cout << "A" << endl;

}

};

int A::m_iSA4 = 0;

 

int main()

{

A *pObjectA=NULL;

pObjectA->print();

return 0; 

}

 

运行成功!静态变量独立于类外部分配好了合法地址,访问成功。

 

2、继承

class B

{

int m_iB1;

public:

virtual void print()

{

cout << "B" << endl;

}

};

 

class A:public B

{

    int m_iA1;

    char m_chA2;

public:

    void print()

    {

        cout << "A" << endl;

    }

};

 

int main()

{

    A *pObjectA=NULL;

    pObjectA->print();

    return 0; 

}

 

运行之后崩在在main函数的红色标记语句。

分析:虽然A类的print函数没有用到显式的成员变量,但是类A继承于类B,print()是继承于B的虚函数,调用A的print函数时,用到了虚表,虚表地址在类对象数据段最开头,此时访问了非法地址。

可以看到成员变量地址:

空指针也不崩溃
 

给pObjectA分配空间之后再看

空指针也不崩溃
 

可以看到,在继承类对象的地址空间中的顺序为:虚表指针、基类成员变量、继承类成员变量

 

通常崩溃报错的对话框中会给出一些关键信息:

空指针也不崩溃
如此图中的0x00411596表示出错的代码段地址,0xC0000000为出错的数据段地址,0xC0000005为错误码。“Access violation”就是此错误码的具体含义,查看所有错误码含义可查阅Visual Studio-Debug-Exceptions-Win32 Exceptions。详细错误信息都会保存在dmp文件中,用Windbg这类工具可以看到详细信息,进行具体分析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章