您的位置:首页 > 编程语言 > C语言/C++

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

2013-05-10 14:39 267 查看
不知道大家有没有看过 陈浩的C++ 对象的内存布局(下),作者给的代码并不能运行

作者文章 :/article/2551888.html

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

#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**)ⅆ

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::ib1

cout << "[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::ib2

cout << "[7] B2::cb2 = ";

cout << (char)*((int*)(&dd)+7) << endl; //B2::cb2

cout << "[8] D::id = ";

cout << *((int*)(&dd)+8) << endl; //D::id

cout << "[9] D::cd = ";

cout << (char)*((int*)(&dd)+9) << endl;//D::cd

cout << "[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::ib

cout << "[13] B::cb = ";

cout << (char)*((int*)(&dd)+13) <<endl;//B::cb

}


运行结果如图


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



估计这篇文章没人看 屌丝文章,就算了,不解释了 无非是调过这句 sub ecx,dword ptr[ecx-4] ,如果加了cout << "[0]"什么的 改了ecx,导致取ecx-4异常违规而已
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: