汇编中的运算符delete()何时删除vptr指针?

发布于 2024-12-19 22:17:37 字数 3581 浏览 1 评论 0原文

当调用操作符delete()时,vptr被删除。

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

我想知道我刚刚创建的对象中的 vptr 到底是什么时候在汇编中被删除。

这是来自 VS2010 的汇编代码(voidoperatordelete(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;

提前致谢。 :)

The vptr is deleted when operator delete() is called.

But the vptr pointer is hidden, and we don't have to care about its memory structure (plus each compiler has a different system on how it works.)

I'd like to know when exactly the vptr in an object that I just made is deleted in assembly.

Here is the assemble code(void operator delete(void * pUserData) ) from VS2010

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;

Thanks in advance. :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

原谅过去的我 2024-12-26 22:17:37

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

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

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

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

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

Caveat: This is an implementation detail. Standard C++ does not dictate how virtual functions should be implemented, and doesn't know what a vtable/vptr is.

The vtable for a type has static duration (meaning it is around for the entire lifetime of the program). Each instance of the type has a vptr to that shared vtable. So the instance does not delete the vtable, because it does not own it.

The storage for the vptr (not the vtable it points to) is part of the instance, and gets deleted with the instance.

During construction/destruction the vptr is set to the vtable for each base class as they are being constructed. Not seeing the most-derived type is the reason people warn against calling virtual functions in the constructor -- you might not be calling the function you expected to be calling.

The vptr is unusable once the final destructor has been called.

末骤雨初歇 2024-12-26 22:17:37

也许这里:

_free_dbg( pUserData, pHead->nBlockUse );

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

Maybe here:

_free_dbg( pUserData, pHead->nBlockUse );

Vptr is part of object, and cannot be deleted separately.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文