当程序集中的operator delete()删除vptr指针时?

时间:2011-12-08 05:55:24

标签: c++ vtable vptr

调用operator delete()时会删除vptr。

但是vptr指针是隐藏的,我们不必关心它的内存结构(加上每个编译器都有不同的系统如何工作。)

我想知道我刚刚制作的对象中的vptr究竟何时被删除。

这是来自VS2010的汇编代码(void operator delete(void * pUserData))

10315980  mov         edi,edi  
10315982  push        ebp  
10315983  mov         ebp,esp  
10315985  push        0FFFFFFFEh  
10315987  push        10350F48h  
1031598C  push        offset _except_handler4 (10319550h)  
10315991  mov         eax,dword ptr fs:[00000000h]  
10315997  push        eax  
10315998  add         esp,0FFFFFFF4h  
1031599B  push        ebx  
1031599C  push        esi  
1031599D  push        edi  
1031599E  mov         eax,dword ptr [___security_cookie (103604BCh)]  
103159A3  xor         dword ptr [ebp-8],eax  
103159A6  xor         eax,ebp  
103159A8  push        eax  
103159A9  lea         eax,[ebp-10h]  
103159AC  mov         dword ptr fs:[00000000h],eax  
    _CrtMemBlockHeader * pHead;

    RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));

    if (pUserData == NULL)
103159B2  cmp         dword ptr [ebp+8],0  
103159B6  jne         operator delete+3Dh (103159BDh)  
        return;
103159B8  jmp         $LN10 (10315A55h)  

    _mlock(_HEAP_LOCK);  /* block other threads */
103159BD  push        4  
103159BF  call        _lock (102496F0h)  
103159C4  add         esp,4  
    __TRY
103159C7  mov         dword ptr [ebp-4],0  

        /* get a pointer to memory block header */
        pHead = pHdr(pUserData);
103159CE  mov         eax,dword ptr [ebp+8]  
103159D1  sub         eax,20h  
103159D4  mov         dword ptr [ebp-1Ch],eax  

         /* verify block type */
        _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
103159D7  mov         ecx,dword ptr [ebp-1Ch]  
103159DA  mov         edx,dword ptr [ecx+14h]  
103159DD  and         edx,0FFFFh  
103159E3  cmp         edx,4  
103159E6  je          operator delete+0A9h (10315A29h)  
103159E8  mov         eax,dword ptr [ebp-1Ch]  
103159EB  cmp         dword ptr [eax+14h],1  
103159EF  je          operator delete+0A9h (10315A29h)  
103159F1  mov         ecx,dword ptr [ebp-1Ch]  
103159F4  mov         edx,dword ptr [ecx+14h]  
103159F7  and         edx,0FFFFh  
103159FD  cmp         edx,2  
10315A00  je          operator delete+0A9h (10315A29h)  
10315A02  mov         eax,dword ptr [ebp-1Ch]  
10315A05  cmp         dword ptr [eax+14h],3  
10315A09  je          operator delete+0A9h (10315A29h)  
10315A0B  push        offset string L"_BLOCK_TYPE_IS_VALID"... (1021CD48h)  
10315A10  push        0  
10315A12  push        34h  
10315A14  push        offset string L"f:\\dd\\vctools\\crt_bl"... (1021CCE0h)  
10315A19  push        2  
10315A1B  call        _CrtDbgReportW (103145F0h)  
10315A20  add         esp,14h  
    10315A23  cmp         eax,1  
10315A26  jne         operator delete+0A9h (10315A29h)  
10315A28  int         3  

        _free_dbg( pUserData, pHead->nBlockUse );
10315A29  mov         edx,dword ptr [ebp-1Ch]  
10315A2C  mov         eax,dword ptr [edx+14h]  
10315A2F  push        eax  
10315A30  mov         ecx,dword ptr [ebp+8]  
10315A33  push        ecx  
10315A34  call        _free_dbg (10316920h)  
10315A39  add         esp,8  

    __FINALLY
10315A3C  mov         dword ptr [ebp-4],0FFFFFFFEh  
10315A43  call        $LN7 (10315A4Ah)  
10315A48  jmp         $LN10 (10315A55h)  
        _munlock(_HEAP_LOCK);  /* release other threads */
10315A4A  push        4  
10315A4C  call        _unlock (10249740h)  
10315A51  add         esp,4  
$LN8:
10315A54  ret  
    __END_TRY_FINALLY

    return;

提前致谢。 :)

2 个答案:

答案 0 :(得分:4)

警告:这是一个实现细节。标准C ++没有规定应该如何实现虚函数,也不知道vtable / vptr是什么。

类型的vtable具有静态持续时间(意味着它在程序的整个生命周期中都存在)。该类型的每个实例都具有该共享vtable的vptr。因此实例不会删除vtable,因为它不拥有它。

vptr的存储(不是它指向的vtable)是实例的一部分,并随实例一起被删除。

在构造/销毁期间,vptr被设置为每个基类在构造时的vtable。没有看到派生最多的类型是人们警告不要在构造函数中调用虚函数的原因 - 你可能没有调用你期望调用的函数。

一旦调用了最终的析构函数,vptr就无法使用。

答案 1 :(得分:3)

也许在这里:

_free_dbg( pUserData, pHead->nBlockUse );

Vptr是对象的一部分,不能单独删除。