汇编中的运算符delete()何时删除vptr指针?
当调用操作符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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
警告:这是一个实现细节。标准 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.
也许这里:
Vptr是对象的一部分,不能单独删除。
Maybe here:
Vptr is part of object, and cannot be deleted separately.