2014-10-10 34 views
-1

爲什麼這段代碼調用錯誤的虛函數?它調用偏移量爲8的函數,而它應該調用偏移量爲4的函數。如果我在8中重命名函數,它會正確調用4的函數。代碼gen bug?我錯過了一些愚蠢的東西?它爲什麼會調用錯誤的虛函數?

來源:

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 
+4

你怎麼知道'bool blit(int)'在哪裏?我不認爲C++標準對vtable佈局有任何說明。 – 2014-10-10 11:52:31

+0

順便說一句,vtable的開頭可以包含其他內容,而不是虛擬方法。 – lisyarus 2014-10-10 11:53:30

+2

這意味着'blit(int)'在偏移量8,而不是4,因爲你相信。 – interjay 2014-10-10 11:53:50

回答

2
int main() 
{ 
    surface_c* surface; // surface contains garbage, as it is uninitialzed 
    surface->blit(0); 
    return 0; 
} 

表面必須指向surface_c的一些非抽象子,例如

surface = new surface_f(); 

其中surface_f是surface_c的一些非抽象子類,並且繼承的純虛函數必須由具體實現

+0

這是關於爲blit調用生成的程序集。我知道表面未初始化,它只是在那裏重現此問題。 – XTF 2014-10-11 22:19:31

1

要調用上未初始化的指針的方法來覆蓋。一個方法被調用是純粹的運氣,程序不會崩潰。

相關問題