C++ 类成员函数

C++ 类成员函数

在进入正题之前,先贴一段代码。
#include <stdio>
class A{
    private:
        int a;
    public:
    void FuncA(){
        printf("hello world!");
    }
    void FuncB(){
        printf("hello world!,%d",a);
    }
    A(){
        a = 0;
    }
};
int main(){
    A *pA = nullptr;
    pA->FuncA();
    pA->FuncB();
    return 0;
}
然后单步调试运行结果是:pA->FuncA();不会崩溃,但是pA->FuncB();会崩溃。为啥。看上去两个几乎一样的函数调用,为啥一个可以运行一个不行。
这里写图片描述

C++中教导我们不可以去调用未初始化类的方法(其实这句话也不是全对)。这里明明没有被初始化pA的FuncA被调用没错。

- 解答

这里我们只需要比较一下两个函数的汇编,即能明显的得到这两个函数的区别。
这里写图片描述

首先看FuncA();我们可以看到将hello world!字符串首地址进行压栈操作之后立马调用了printf然后将字符串打印,然后校验rsp(一般debug环境下专有,在函数调用返回之前起平衡堆栈的作用)。没有涉及到动态内存的访问,FuncA()所在的代码段并没有引用任何的非法内存。
FuncA

然后看FuncB(),这里的这三句话,将this指针转存到ecx,然后传递给printf,这里由于this指针为nullptr(因为pA为nullptr,所以取不到A非法内存访问崩溃)。
FuncB
这里差别在汇编看来,除了最后的调用printf之外,只有FuncB进行了非法内存(a的指针)的访问,由于a的指针和pA的值一样,所以指向0地址的值,这样就造成了非法内存访问。

究其本质,其实C++在类成员函数调用时,差不多作可以这样理解:将一个void A::Func(….)转换为,void Func(….,void *pThis)形式,将自己this指针作为一个参数传递给自身的成员函数,然后在汇编中,通过ecx传递this指针的值,成员函数整个编译成二进制代码,成员函数通过基址+偏移的方式访问类的成员变量。

这样只要访问自己的成员变量的成员函数,在对象不存在,由于基址(就是this指针)非法,造成因为通过基址+偏移的方式访问的成员变量非法,这样就会造成非法内存访问。也并不是单纯的去调用未初始化类的方法一定会崩,关键看内存访问。

还有一条,就是类的代码段和数据段是独立的,即使类的数据域为null,他的类成员函数(包括各种构造析构函数,代码段)都是存在于编译之后的exe中的。类的数据为空,并不影响他代码段的使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值