您的位置:程序门 -> c/c++ -> c++ 语言



怎么得到一个虚函数的实际地址


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


怎么得到一个虚函数的实际地址
发表于:2007-07-16 17:27:50 楼主
菜了,晕了,问个问题

struct   base
{
        virtual   void   fun1(){}
        virtual   void   fun2(){}
        virtual   void   fun3(){}
};

struct   device   :   public   base
{
        virtual   void   fun1(){}
        virtual   void   fun2(){}
        virtual   void   fun3(){}
};

base*   createobj()
{
          return   new   device;
}
....

        base*   pp   =   createobj();

        pp-> fun3();  

        我想得到pp-> fun3();的函数地址(在这里是   device::fun3())

        当只知道base的定义,和   createobj   函数的时候

        然后得到这个真实的函数地址fun3()

        其实,可以通过查找虚函数表的第3个函数就可以了

        但当连第几个都不知道(只知道函数名)的时候如何做呢

       

....


分都散完了,就一点,喜欢大家帮忙
发表于:2007-07-16 18:42:121楼 得分:0
up   -   -
发表于:2007-07-16 19:56:092楼 得分:0
void   (*pf)()=&device::fun3;
pp-> *pf();
发表于:2007-07-16 20:25:413楼 得分:0
uwinb没理解问的问题,关键在不知道它是base的还是device的.
发表于:2007-07-16 20:42:434楼 得分:0
up
发表于:2007-07-16 21:21:315楼 得分:0
来看看   chiyer(星羽)   会问点什么问题   ...
发表于:2007-07-16 21:27:336楼 得分:0
沙发没了,板凳没了,连地板都没了,只好up一下了-   -
发表于:2007-07-16 22:12:287楼 得分:0
虫子,帮我看看啊,怎么进来就跑了。。。。
发表于:2007-07-16 22:32:278楼 得分:0
这应该是mission   impossible了...
连位置都定不了,也就是说函数声明顺序一变,表项的位置也一样变了...况且这个跟编译器还密切相关吧,   我没查c++标准,不知道对vtbl的顺序有啥要求没.
发表于:2007-07-16 23:25:539楼 得分:0
pp-> fun3
难道这样不行么
发表于:2007-07-16 23:38:4010楼 得分:0
mark
发表于:2007-07-17 08:32:2411楼 得分:0
你为什么需要获得虚函数的实际地址?
发表于:2007-07-17 08:35:4812楼 得分:0
个人感觉你可以参考com的实现机制,用qi来做。
发表于:2007-07-17 08:48:3513楼 得分:0
和编译器放置虚表指针位置有关,否则不可能,知道虚表位置就不用我再说了吧

星羽也来问问题啊:)
发表于:2007-07-17 09:15:0414楼 得分:0
呵呵

算了这样问吧,然后知道某个虚函数在虚函数表上的位置(不要说是去看.h   =   =)
发表于:2007-07-17 09:18:2915楼 得分:0
派生类的虚表中虚函数地址的排列顺序和基类的虚表中虚函数地址排列顺序相同。
不了解基类。。。的~~
发表于:2007-07-17 09:20:2316楼 得分:0
com   的   qi接口倒是可以参考一下   ...
发表于:2007-07-17 09:22:0917楼 得分:0
恩恩,不要死钻嘛~虫子出现喽星羽
发表于:2007-07-17 09:24:2218楼 得分:0
不会
帮你顶一下
发表于:2007-07-17 09:25:5519楼 得分:0
就算看了.h你都未必知道它在虚表上的位置。
因为根据c++的(未)规定,编译器自行决定虚表里的函数排列顺序。
完全可以有编译器根据函数类型进行排序构建虚表。
你可以知道某一个编译器下的情况,却无法推广到所有编译器。
试图确定函数在虚表中的位置是不合理的解。
应该根据原始需求找合理解。
发表于:2007-07-17 09:28:1920楼 得分:0
恩恩,taodm说的是,不要去追求非标准的东西,星羽大概是玩mfc过多了,也爱上了非标准的蛮技了~
发表于:2007-07-17 11:11:3221楼 得分:0


我其实想   hook   一个通过导出接口调用的函数,而且这个函数还是虚的,我不知道怎么弄

比如

idirect3d*   p   =   direct3dcreate(....);

dll里只导出了   direct3dcreate

但我要hook的是   p-> setrenderstate()这个虚函数,不知道怎么办了
发表于:2007-07-17 11:16:3422楼 得分:0
确定编译器下的确定类,自己用调试先跟出实际地址再搞就是了。
发表于:2007-07-17 11:28:1723楼 得分:0
如果你写code时已经确定base都有哪些派生类,就可以:
if   (dynamic_cast <derived> (p)   !=   null)
{
pf   =   &derived::fun3;
}
else   if   ((dynamic_cast <derived1> (p)   !=   null)
{
pf   =   &derived1::fun3;
}
else   ...
发表于:2007-07-17 11:31:1624楼 得分:0
哦,另外一种方法是:
struct   base{
...
virtual   void*   getfun3ptr(void)const
{
return   &base::fun3;
}
};
然后为每个派生类实现这个方法
发表于:2007-07-17 11:35:4925楼 得分:0
虚函数表是编译器实现定义的东西,不具有通用性和稳定性,通常也没有正式的文档.

牛人教育过我们,不要用x射线照射编译器.
发表于:2007-07-17 11:37:5326楼 得分:0
“不要用x射线照射编译器”
哈哈,编译器有时就是流氓
说得好!
发表于:2007-07-17 11:53:2327楼 得分:0
[quote]
我其实想   hook   一个通过导出接口调用的函数,而且这个函数还是虚的,我不知道怎么弄

比如

idirect3d*   p   =   direct3dcreate(....);

dll里只导出了   direct3dcreate

但我要hook的是   p-> setrenderstate()这个虚函数,不知道怎么办了
[/quote]
虚函数不能是静态的,搞不懂你的hook是如何定义的,难道这个hook的第一个参数也是this?

既然是dll,那么它里面一定有p-> setrenderstate所对应的符号,这个selector根据p找到真正使用的需函数,所以完全可以hook这个符号对应的地址,而无需知道虚函数的真正地址。

各个子类的虚函数实现在dll里都会有相应的符号,理论上是可以找到这个地址的,现在缺少的是一致的机制去根据p定位到这些函数。如果你可以修改dll得源码,你可以增加机制完成需要的功能,如果不能修改dll原码,恐怕是没有通用的方案...
发表于:2007-07-17 13:01:5628楼 得分:0
虚函数中,有虚表啊。。。     虚表记录了对应函数的地址开始点。。
发表于:2007-07-17 16:47:5729楼 得分:0
俄,mark一把
发表于:2007-07-17 17:42:3730楼 得分:0
template   <typename   t>
pvoid   queryvirtualfunaddress(pvoid   pinstance,   t   pmemfun)
{
        if   (!pinstance)
                return   null;

        const   dword   dwcode1   =   0x0424448b;
        const   dword   dwcode2   =   0xa0ff008b;
        const   dword   dwcode3   =   0x20ff008b;

        pdword   dwcode   =   (pdword)(dword_ptr)*(pdword)&pmemfun;
        dword     index     =   0;

        if   (dwcode[0]   !=   dwcode1)
                return   null;

        if   (dwcode[1]   ==   dwcode3)
                index   =   0;
        else   if   (dwcode[1]   ==   dwcode2)
                index   =     (int)dwcode[2]   /   4;
        else
                return   null;


        pdword   addr   =   (pdword)(dword_ptr)(pinstance);
        pdword   vptr   =   (pdword)(dword_ptr)(*addr);

        return   (pvoid)(vptr[index]);        


}

void*   p   =   queryvirtualfunaddress(g_pd3ddevice,   &idirect3ddevice9::setrenderstate);


没任何移植性,在windows   +   vc2005   才良好

我就只能想出这个办法了
发表于:2007-07-17 17:42:5631楼 得分:0
高手不要k我啊
发表于:2007-07-17 21:54:2832楼 得分:0
学习学习


快速检索

最新资讯
热门点击