异想天开

What's the true meaning of light, Could you tell me why

c++的多继承this指针调整

日期:2014-10-22 16:24:28
  
最后更新日期:2014-10-22 16:48:21
【说在前面】
好久没看过汇编代码了,有点“费力”。开始看到call *%rdx这条指令,想了一会儿,我的理解中,call寄存器里面的地址,就直接call %rdx这样表达即可。无
奈,调试才发现call *%rdx表达了call %rdx的意思。兴冲冲查看寄存器的值。
[code lang="cpp"]
(gdb) info reg rax
rax 0x400f90 4198288
[/code]
咋看起来,rax为8个字节,4198288是8字节的高位吧,开始是这么想的。后面才发现这个值为0x400f90的十进制值。突然发现gdb好邪恶。
问题1. 这样的继承关系
class a
class b
class c: public a,public b
b* p= new c
p->fun a,b,c都有的虚函数
有几张虚表,p->fun的this指针会调整么?(PS:笔者起先并不知道它会调整,故这里的问题并不是该怎么调整,后续部分算是怎么调整的问题)
开始推断有3张虚表,a,b,c分别一张。每次找函数地址时,都在自己的虚表里面找。这样也就有3个this指针。后来测试了gcc里面的实现机制。只有两张虚表,两个this指针。测试源码后附。先看两段关键汇编。
经过几轮间接寻址,rdx就是正确的b的testb函数地址。rdi即p指针的值。
2 call *%rdx后的汇编:
3 这里先将rdi减18,意思即调整this指针,然后跳到c::testb里面去执行。所有的这些调整都是编译时期就确定好的,因为根据iso c++的语义就可以决定是哪个函数,就可以跳过去。参考1说是执行时确定,没搞明白为啥这么说,看明白了的看官,留个信。
测试代码:
[code lang="cpp"]
//64位系统 centos
#include<iostream>
using namespace std;

class a{
public:
a(){
cout<<"a: "<<this<<endl;
}
virtual void testa(){}
int _a0,_a1,_a2;
virtual ~a(){}
};

class b{
public:
b(){
cout<<"b: "<<this<<endl;
}
virtual void testb1(){}
virtual void testb(){ cout<<"b testb this:"<<this<<endl;}
int _b;
virtual ~b(){}
};

class c: public a, public b{
public:
c(){
cout<<"c: "<<this<<endl;
}
virtual void testb(){ cout<<"c testb this:"<<this<<en
virtual void testc(){}
int _c;
virtual ~c(){}
};

class d: public c{
public:
d(){
cout<<"d: "<<this<<endl;
}
int _d;
};
int main()
{
b* p=new c;
p->testb();
p->b::testb();
delete p;
return 0;
}
[/code]
参考1:
http://www.cnblogs.com/lbsx/archive/2011/04/18/2020009.html