【问题标题】:Why does it call wrong virtual function?为什么会调用错误的虚函数?
【发布时间】:2014-10-10 11:49:51
【问题描述】:

为什么这段代码调用了错误的虚函数?它调用偏移量 8 处的那个,而它应该调用偏移量 4 处的那个。如果我在 8 处重命名函数,它会正确调用 4 处的那个。代码生成错误?我错过了什么愚蠢的东西?

来源:

class surface_c
{
public:
    virtual ~surface_c() = 0; // 0
    virtual bool blit(int) = 0; // 4
    virtual bool blit() = 0; // 8
};

int main()
{
    surface_c* surface;
    surface->blit(0);
    return 0;
}

反汇编:

int main()
{
00A11250  push        ebp  
00A11251  mov         ebp,esp  
00A11253  sub         esp,44h  
00A11256  push        ebx  
00A11257  push        esi  
00A11258  push        edi  
    surface_c* surface;
    surface->blit(0);
00A11259  push        0  
00A1125B  mov         eax,dword ptr [surface]  
00A1125E  mov         edx,dword ptr [eax]  
00A11260  mov         ecx,dword ptr [surface]  
00A11263  mov         eax,dword ptr [edx+8]  
00A11266  call        eax  
    return 0;
00A11268  xor         eax,eax  
}
00A1126A  pop         edi  
00A1126B  pop         esi  
00A1126C  pop         ebx  
00A1126D  mov         esp,ebp  
00A1126F  pop         ebp  
00A11270  ret  

【问题讨论】:

  • 你怎么知道bool blit(int)的位置?我不认为 C++ 标准对 vtable 布局有任何说明。
  • 顺便说一句,vtable 的开头可以包含其他东西,而不是虚拟方法。
  • 这意味着blit(int) 位于偏移量 8,而不是您认为的 4。
  • @Tobias 对了,VC2013如何对vtable中的函数进行排序?我知道它是定义的实现。通常我不在乎,但这是一个逆向工程项目(游戏 Red Alert 2 的),我需要匹配原始的 vtable 布局。
  • 那么也许你应该编辑你的问题(或开始一个新问题)来询问VC的vtable布局。

标签: c++ visual-studio-2013 virtual


【解决方案1】:
int main()
{
    surface_c* surface; // surface contains garbage, as it is uninitialzed
    surface->blit(0);
    return 0;
}

surface 必须指向surface_c 的某个非抽象子类,例如

surface = new surface_f();

其中surface_f是surface_c的一些非抽象子类,继承的纯虚函数必须被具体实现覆盖

【讨论】:

  • 这是关于为 blit 调用生成的程序集。我知道表面未初始化,它只是为了重现这个问题。
【解决方案2】:

您正在对未初始化的指针调用该方法。调用了一个方法,程序没有崩溃,这纯属运气。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 2011-06-04
    • 2019-01-03
    • 2011-05-07
    • 2015-08-27
    相关资源
    最近更新 更多