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. :)
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.