欢迎加入我们的QQ群,无论你是否工作,学生,只要有c / vc / c++ 编程经验,就来吧!
158427611
1.你关于一个C C++ 内存的问题
栈不需要程序分配,
在程序启动的时候,栈空间就已经分配好了,函数调用结束后,内存并没有释放,只是管理栈的指针(sp寄存器)发生了变化,所以这个内存还是可以访问的。
用以解释一下代码:
void f(int ** p)
{
int i = 5;
*p =&i;
}
void main()
{
int * q = NULL;
f(&q);
cout << q << " = " << *q << endl; // 地址=5
*q = 10;
cout << q << " = " << *q << endl;// 地址= 10;
f(&q);
cout << q << " = " << *q << endl; // 地址=5
*q = 10;
cout << q << " = " << *q << endl;// 地址= 10;
}
程序一启动,其实内存都是可用的,除了一些硬件设防的区域外(这个区域是操作系统设立的禁区)。然后操作系统会分配一块内存给程序,用作栈空间,并且会用一个sp寄存器指向栈顶,如果你的函数定义了一个int变量,那么编译器会自动将sp+4,以腾出空间放这个int的内容。在函数结束时,会将sp-4.这个过程是编译器完成的,无需你来管理。但内存一直是可以访问的。
2.再记一下关于C++ 虚函数表的一些点
存在虚函数的类 ,他的实例会把虚函数表存放到类内存的最开始处,确实能提高函数调用速度,呵呵。
关于虚函数表中,各个函数的存放位置顺序:
单继承中,虚函数表中的顺序就是函数的声明顺序,同时以继承自父类的方法在先,再到未覆盖的父类的,再到自己定义的...
[func1][func2][func3][func自己滴]
也可以看图:
多继承中,继承几个就有几个虚函数表,依次从实例的起始内存地址开始,以继承顺序排序,其各个虚函数表中的顺序同单继承的,但是类自己定义的方法则只在第一个虚函数表中排在后面。
[p1func1][p1func2][p1func3][func自己滴1][func自己滴2]....
[p2func1][p2func2][p2func3]....
[p3func1][p3func2][p3func3]....
看图 :
知道这些之后我们就能干很多 违反 C++ 安全控制的事情啦。。。
看看下面我要说的你就知道了
1. 基类指针调用子类的自定义方法。
2.调用非public的成员函数
参考方法 :
class Base {
private:
virtual void f() { cout << "Base::f" << endl; }
};
class Derive : public Base{
};
typedef void(*Fun)(void);
void main() {
Derive d;
Fun pFun = (Fun)*((int*)*(int*)(&d)+0);
pFun();
}
你会发现输出的就是Base::f的。。。嘿嘿。。。。
用到的就是根据虚函数表的方法顺序分布来做到的。嘿嘿....
64位cpu的情况,64位的指针转换不是int *,应该是long *,否则Segmentation fault (core dumped)
[p1func1][p1func2][p1func3][func自己滴1][func自己滴2]....
[p1func1][p1func2][p1func3][func自己滴1][func自己滴2]....
欢迎加入我们的QQ群,无论你是否工作,学生,只要有c / vc / c++ 编程经验,就来吧!
158427611