一段C++代码想到的问题
今天在学习《Unix环境高级编程》,第七章进程环境给出了一个进程的内存分布示意图,从下往上依次为“正文段->初始化数据->未初始化数据(默认初始化为0)->堆(从低地址到高地址)->栈(从高地址到低地址)->命令行参数和环境变量”。其中的正文段也叫代码段,是可共享的,只读的。
这个时候我就想到上次做的腾讯的一个题目,其实很简单,大概意思如下所示代码所示。大概意思是,先创建了一个类的对象a,再将a内存清0,然后直接调用两个的一个是虚函数一个是非虚函数,看看能否正确访问。另一个是创建了一个类的对象指针,然后将该内存区域清0,通过指针调用类的这两个函数。
结果如代码中所示。当时还无法理解为什么是这样,今天看了这个就试着分析下。首先A中的函数,无论是虚函数还是非虚函数都在编译器被放在进程的代码段,等待被调用。通过直接调用,会直接在代码段找相应的函数调用即可,因此第一种情况下都是正确运行的。而通过指针调用,如果是非虚函数则会直接在代码段调用相应的函数,而如果是虚函数,则会通过指向对象的内存中的虚函数指针找到虚函数表,调用相应的在代码段的虚函数。清零的情况下,虚函数指针已经不复存在了,因此会出现访问虚函数出错。
#include<iostream> #include<string> using namespace std; class A { public: int a; virtual int vfun() { cout << "virtual"; return 0; } void notvfun() { cout << "not virtual"; } }; class B { }; int main() { A a; memset(&a, 0, sizeof(A)); a.notvfun();//right a.vfun(); //right A *pa=new(A); memset(pa, 0, sizeof(A)); pa->notvfun();//right pa->vfun();//wrong }