陈浩 C++ 对象的内存布局(下)勘误

来源:互联网 发布:佳能 35 1.4 知乎 编辑:程序博客网 时间:2024/06/17 22:13

不知道大家有没有看过 陈浩的C++ 对象的内存布局(下),作者给的代码并不能运行

作者文章 :http://blog.csdn.net/haoel/article/details/3081328

 

我改过的代码如下 重点是这句

 

#include "stdafx.h"#include <iostream>#include <string>#include <vector>#include <list>using namespace std;class B{public:int ib;char cb;public:B():ib(0),cb('B') {}virtual void f() { cout << "B::f()" << endl;}virtual void Bf() { cout << "B::Bf()" << endl;}};class B1 : virtual public B{public:int ib1;char cb1;public:B1():ib1(11),cb1('1') {}virtual void f() { cout << "B1::f()" << endl;}virtual void f1() { cout << "B1::f1()" << endl;}virtual void Bf1() { cout << "B1::Bf1()" << endl;}};class B2: virtual public B{public:int ib2;char cb2;public:B2():ib2(12),cb2('2') {}virtual void f() { cout << "B2::f()" << endl;}virtual void f2() { cout << "B2::f2()" << endl;}virtual void Bf2() { cout << "B2::Bf2()" << endl;}};class D : public B1, public B2{public:int id;char cd;public:D():id(100),cd('D') {}virtual void f() { cout << "D::f()" << endl;}virtual void f1() { cout << "D::f1()" << endl;}virtual void f2() { cout << "D::f2()" << endl;}virtual void Df() { cout << "D::Df()" << endl;}};void main(){D dd;typedef void(*Fun)(void);int** pVtab = NULL;Fun pFun = NULL;pVtab = (int**)&dd;cout << "[0] D::B1::_vptr->" << endl;pFun = (Fun)pVtab[0][0];cout << "     [0] ";    pFun(); //D::f1();pFun = (Fun)pVtab[0][1];cout << "     [1] ";    pFun(); //B1::Bf1();pFun = (Fun)pVtab[0][2];cout << "     [2] ";    pFun(); //D::Df();pFun = (Fun)pVtab[0][3];cout << "     [3] ";cout << pFun << endl;//cout << pVtab[4][2] << endl;cout << "[1] = 0x";cout <<  (int*)((&dd)+1) <<endl; //????cout << "[2] B1::ib1 = ";cout << *((int*)(&dd)+2) <<endl; //B1::ib1cout << "[3] B1::cb1 = ";cout << (char)*((int*)(&dd)+3) << endl; //B1::cb1//---------------------cout << "[4] D::B2::_vptr->" << endl;pFun = (Fun)pVtab[4][0];cout << "     [0] ";    pFun(); //D::f2();pFun = (Fun)pVtab[4][1];cout << "     [1] ";    pFun(); //B2::Bf2();pFun = (Fun)pVtab[4][2];cout << "     [2] ";cout << pFun << endl;cout << "[5] = 0x";cout << *((int*)(&dd)+5) << endl; // ???cout << "[6] B2::ib2 = ";cout << (int)*((int*)(&dd)+6) <<endl; //B2::ib2cout << "[7] B2::cb2 = ";cout << (char)*((int*)(&dd)+7) << endl; //B2::cb2cout << "[8] D::id = ";cout << *((int*)(&dd)+8) << endl; //D::idcout << "[9] D::cd = ";cout << (char)*((int*)(&dd)+9) << endl;//D::cdcout << "[10]  = 0x";cout << (int*)*((int*)(&dd)+10) << endl;//---------------------cout << "[11] D::B::_vptr->" << endl;pFun = (Fun)pVtab[11][0];int temp = 0;__asm{mov temp, ecx //保存原始的ecx}//原始例子中注释掉 cout << "     [0] ";这句就行,不注释的话也可以这样做cout << "     [0] ";    //pFun(); //D::f();//pFun();__asm{mov ecx, temp //还原过来}pFun(); //这样就可以直接调用了__asm{call pFun //继续汇编调用方法 简单直接call}//不用还原ecx  都可以直接调用 ,大家可以把上面的保护ecx操作注释掉试试__asm{mov edx, pFun;mov eax, [edx]shr eax, 8 //调整偏移add eax, 5  add edx, eax;add edx, 3 //由于thunk  就是那个vdisp什么的,必须跳过 sub ecx, [ecx-4]这句call edx  }pFun = (Fun)pVtab[11][1];cout << "     [1] ";    pFun(); //B::Bf();pFun = (Fun)pVtab[11][2];cout << "     [2] ";cout << pFun << endl;cout << "[12] B::ib = ";cout << *((int*)(&dd)+12) << endl; //B::ibcout << "[13] B::cb = ";cout << (char)*((int*)(&dd)+13) <<endl;//B::cb}


运行结果如图

之所以要调过那个ecx-4是因为图形

估计这篇文章没人看 屌丝文章,就算了,不解释了 无非是调过这句 sub ecx,dword ptr[ecx-4]  ,如果加了cout << "[0]"什么的 改了ecx,导致取ecx-4异常违规而已