VS hide switch

在看雪学院的 <<逆向C++>>一文中偶尔看到说VC6.0 以上的编译器支持一个d1reportAllClassLayout的开关, 可以输出所有对象的内存布局信息, 心想我不知道多少次查看过 cl /?的输出, 没印象这个玩艺儿呀, 打开cmd窗口, 弄了个例子程序, 一试不爽.
小例子程序如下:

struct Foo
{
        int i;
        char c;
};
int main()
{
        Foo f;
        f.i = 5;
        return 0;
}

这个开关输出了包括Foo结构在内, 主要是一大堆编译器内部的结构的内存布局, 其实还有一个开关是
d1reportSingleClassLayout
用起来是这样:
cl -d1reportSingleClassLayoutFoo test.cpp
切切注意, Layout跟指定的结构/类名Foo之间没有空格, 有空格就不对了. 这会只输出指定的结构的内存布局.

遗憾的是, 不能多次指定 -d1reportSingleClassLayout以输出多个自定义的结构的内存布局. 而且也不支持通配符*之类.

在google里搜了一下, msvc hidden switch, 本想顺藤摸瓜找出MSVC支持的所有隐藏开关, 没发现什么其它的.

在VS测试小组
Andy Rich的blog中, 说这样的选项未经公布, 也没做测试, 使用者责任自负. 呵呵, 这是当然. 不论如何, 有这个总比没有好.

下面看看对包含了虚函数的类的输出:




class Foo
{
    public:
    int i;
    virtual void foo();
    char c;
};

void Foo::foo()
{
}
int main()
{
    Foo f;
    f.i = 5;
    return 0;
}

输出是:


不光给出了对象布局开关处的vfptr指针, 而且连带的输出了Foo对象的vtable. 最后的那个this adjustor是什么? 估计是多重继承时如何调整this指针的一个偏移量. 放在这, 估计日后用得着.

======================================================================================

MSVC++ compiler /d1reportSingleClassLayout /d1reportAllClassLayout

Some undocumented parameter in MSVC++ compiler
/d1reportSingleClassLayout<name> and /d1reportAllClassLayout

Example1
// v.cpp

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 : 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: 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;}

};



E:\>cl v.cpp -d1reportSingleClassLayoutD
...
class D size(48):
+---
| +--- (base class B1)
| | +--- (base class B)
0 | | | {vfptr}
4 | | | ib
8 | | | cb
| | | <alignment member> (size=3)
| | +---
12 | | ib1
16 | | cb1
| | <alignment member> (size=3)
| +---
| +--- (base class B2)
| | +--- (base class B)
20 | | | {vfptr}
24 | | | ib
28 | | | cb
| | | <alignment member> (size=3)
| | +---
32 | | ib2
36 | | cb2
| | <alignment member> (size=3)
| +---
40 | id
44 | cd
| <alignment member> (size=3)
+---

D::$vftable@B1@:
| &D_meta
| 0
0 | &D::f
1 | &B::Bf
2 | &D::f1
3 | &B1::Bf1
4 | &D::Df

D::$vftable@B2@:
| -20
0 | &thunk: this-=20; goto D::f
1 | &B::Bf
2 | &D::f2 //f2的this adjustor: 20
3 | &B2::Bf2

D::f this adjustor: 0 //B1和B2都有f,B2的f需要对this-=20,但B1不需要
D::f1 this adjustor: 0
D::f2 this adjustor: 20
D::Df this adjustor: 0

Example2

// v2.cpp

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;}

};


E:\>cl v2.cpp -d1reportSingleClassLayoutD
...
class B size(12):
+---
0 | {vfptr}
4 | ib
8 | cb
| <alignment member> (size=3)
+---

B::$vftable@:
| &B_meta
| 0
0 | &B::f
1 | &B::Bf

B::f this adjustor: 0
B::Bf this adjustor: 0


class B1 size(32):
+---
0 | {vfptr}
4 | {vbptr}
8 | ib1
12 | cb1
| <alignment member> (size=3)
+---
16 | (vtordisp for vbase B)
+--- (virtual base B)
20 | {vfptr}
24 | ib
28 | cb
| <alignment member> (size=3)
+---

B1::$vftable@B1@:
| &B1_meta
| 0
0 | &B1::f1
1 | &B1::Bf1

B1::$vbtable@:
0 | -4
1 | 16 (B1d(B1+4)B)

B1::$vftable@B@:
| -20
0 | &(vtordisp) B1::f
1 | &B::Bf

B1::f this adjustor: 20
B1::f1 this adjustor: 0
B1::Bf1 this adjustor: 0

vbi: class offset o.vbptr o.vbte fVtorDisp
B 20 4 4 1


class B2 size(32):
+---
0 | {vfptr}
4 | {vbptr}
8 | ib2
12 | cb2
| <alignment member> (size=3)
+---
16 | (vtordisp for vbase B)
+--- (virtual base B)
20 | {vfptr}
24 | ib
28 | cb
| <alignment member> (size=3)
+---

B2::$vftable@B2@:
| &B2_meta
| 0
0 | &B2::f2
1 | &B2::Bf2

B2::$vbtable@:
0 | -4
1 | 16 (B2d(B2+4)B)

B2::$vftable@B@:
| -20
0 | &(vtordisp) B2::f
1 | &B::Bf

B2::f this adjustor: 20
B2::f2 this adjustor: 0
B2::Bf2 this adjustor: 0

vbi: class offset o.vbptr o.vbte fVtorDisp
B 20 4 4 1


class D size(56):
+---
| +--- (base class B1)
0 | | {vfptr}
4 | | {vbptr}
8 | | ib1
12 | | cb1
| | <alignment member> (size=3)
| +---
| +--- (base class B2)
16 | | {vfptr}
20 | | {vbptr}
24 | | ib2
28 | | cb2
| | <alignment member> (size=3)
| +---
32 | id
36 | cd
| <alignment member> (size=3)
+---
40 | (vtordisp for vbase B)
+--- (virtual base B)
44 | {vfptr}
48 | ib
52 | cb
| <alignment member> (size=3)
+---

D::$vftable@B1@:
| &D_meta
| 0
0 | &D::f1
1 | &B1::Bf1
2 | &D::Df

D::$vftable@B2@:
| -16
0 | &D::f2
1 | &B2::Bf2

D::$vbtable@B1@:
0 | -4
1 | 40 (Dd(B1+4)B)

D::$vbtable@B2@:
0 | -4
1 | 24 (Dd(B2+4)B)

D::$vftable@B@:
| -44
0 | &(vtordisp) D::f
1 | &B::Bf

D::f this adjustor: 44
D::f1 this adjustor: 0
D::f2 this adjustor: 16
D::Df this adjustor: 0

vbi: class offset o.vbptr o.vbte fVtorDisp
B 44 4 4 1

What is vtordisp for vbase B ?

Thr vtordisp is an offset that is used if you call any virtual functions in the constructor and destructor.

It is used very rarely - but we have to add it to classes that inherit from a virtual base class and override virtual functions just in case the user does call a virtual function in the constructor or destructor.

 

http://msdn.microsoft.com/en-us/library/ms879782.aspx

Enables the addition of the hidden vtordisp construction/destruction displacement member. The vtordisp pragma is applicable only to code that uses virtual bases. If a derived class overrides a virtual function that it inherits from a virtual base class, and if a constructor or destructor for the derived class calls that function using a pointer to the virtual base class, the compiler may introduce additional hidden “vtordisp” fields into classes with virtual bases.

The vtordisp pragma affects the layout of classes that follow it. The /vd0 and /vd1 options specify the same behavior for complete modules. Specifying off suppresses the hidden vtordisp members. Specifying on, the default, enables them where they are necessary. Turn off vtordisp only if there is no possibility that the class’s constructors and destructors call virtual functions on the object pointed to by the this pointer.\

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值