哪位高手可以谈谈c++里面的Thunk技术

谁可以谈谈c++里面的Thunk技术在看对象模型这本书,里面讲函数的那章提到thunk。网上搜了一下,发现一个代码:

谁可以谈谈c++里面的Thunk技术
在   看对象模型这本书,里面讲函数的那章提到thunk。

网上搜了一下,发现一个代码:

//   此程序演示   运行时   改变   指令代码      
   
//实质是   C++   实现多态     的   THUNK   技术思想的简陋模拟  

//在VC6.0   中编译通过。  

#include   <windows.h>  
#include   <iostream.h>  



typedef   void(*pFUN)();//函数类型  

#pragma   pack(push,1)//强制编译器,使数据按字节边界对齐。  
//默认情况下VC6.0是按4字节对齐,VC7.0按8字节对齐  
//指令本不是按双字边界对齐的,所以必须使其按字节边界对齐,否则出错  

//   下面是存储机器代码的结构  
struct   Thunk//有趣的是:这个结构不储存数据,而是储存指令。一个jmp跳转指令  
{         //我们将改变这个结构,然后让程序执行此代码,此结构的执行将会改变程序的执行路径  
        BYTE         m_jmp;//   储存jmp指令的操作码  
   
DWORD       m_adrr;//   储存相对jmp指令的偏移地址(指令操作数)  
};


#pragma   pack(pop)//撤销数据按字节对齐,数据按双字对齐的主要目的是优化执行速度  

class   C  
{  
public:  
        Thunk         m_thunk;//产生一个   Thunk   实例  

        void   Init(pFUN   pFun)  
        {  
                 
                m_thunk.m_jmp   =   0xe9;//   跳转指令的操作码是   0xe9   所以。。。  
               
                m_thunk.m_adrr   =   (int)pFun   -   ((int)this+sizeof(Thunk));  
                //   JMP跳转是相对跳转,也就是说:它是跳转到的地址是:   当前指令地址(EIP)+相对操作数  
//   相对操作数有符号的!  
                //当指令执行到Thunk   中指令的时候,我们需要跳转到pFun,而当前EIP指为(int)this+sizeof(Thunk)  
//原因:在顺序执行指令时,EIP在执行一条指令后会自动增,这里当然增的是sizeof(Thunk)  
//又由于没有virtual指针,所以   m_thunk的地址就是this指向地址,但是执行此指令后EIP会自动加,
//所以EIP内容为(int)this+sizeof(Thunk)  
//所以   pFun=m_thunk.m_adrr+((int)this+sizeof(Thunk)),移项可得上式  


FlushInstructionCache(GetCurrentProcess(),     &m_thunk,   sizeof(m_thunk));   //强制刷新指令缓冲,  
                                                                              //目的是使指令CACHE与主存相一致  

        }  
        //实验的第一函数  
void   function()  
        {  
                //   初始化thunk  
                //   获得thunk代码地址  
                pFUN   pFun   =   (pFUN)&(m_thunk);  

                //   调用StaticFun  
                pFun();        
        }  
        static   void   Fun1()  
        {  


                cout   < <   "this   is   Fun1 "   < <   endl;  
        }  

static   void   Fun2()    
{  
cout   < <   "this   is   Fun2 "   < <   endl;  
}  
};  

int   main()  
{  
      C   *pC=new   C;  

      pC-> Init(C::Fun1);  
      pC-> function();   //1  

      pC-> Init(C::Fun2);  
       
      pC-> function();//2  
       
      //请注意,上面调用同一个函数,第一个执行的是C::Fun1,第二个却执行的是C::Fun2  
      //这充分说明实现了多态性!  
        return   0;  
}  

有没有达人可以指点指点这个程序,或者剖析下Thunk
xiexie

[解决办法]
http://dev.rdxx.com/VC/2002-11/24/041122480.shtml
[解决办法]
这篇不错:)
http://dev.csdn.net/develop/article/15/15747.shtm
[解决办法]
这种方法相对比较底层了,而且也不是什么新技术,ATL就利用这个来实现windows消息处理函数的自动跳转,解决“动态”消息处理函数的问题。

THUNK其实就是一条汇编指令,操作码是0xe9,就是jmp,后面的m_adrr为操作数,这条指令应该是占32个字节的(即addr只有后3位有效,这个我不太确定,还要翻手册)执行这条指令就是跳转到你注册的函数上继续运行。如果函数带有参数,这里还需要考虑堆栈的问题。这其实是利用了“指令=数据”的原理,为每个对象动态地加上一条指令来完成动态跳转,这和我们普通程序里面指令被写死无法修改不太一样。

这种做法显然是平台相关的,如果你看ATL的源码就知道了,VC6的ATL分别为x86平台和另一个处理器(是Alpha还是PowerPC不记得了)定义了2套不同的实现,换句话说,这两个平台之外的平台,ATL是玩不转的。