Когда оператор delete () в сборке удаляет указатель vptr? - PullRequest
0 голосов
/ 08 декабря 2011

vptr удаляется при вызове оператора delete ().

Но указатель vptr скрыт, и нам не нужно заботиться о его структуре памяти (плюс у каждого компилятора своя система работы).

Я хотел бы знать, когда именно vptr в только что созданном объекте удаляется в сборке.

Вот код сборки (оператор void delete (void * pUserData)) из 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;

Спасибо заранее. :)

Ответы [ 2 ]

4 голосов
/ 08 декабря 2011

Предостережение : Это деталь реализации. Стандартный C ++ не определяет, как должны быть реализованы виртуальные функции, и не знает, что такое vtable / vptr.

vtable для типа имеет статическую длительность (то есть он существует в течение всего времени жизни программы). Каждый экземпляр типа имеет vptr для этой общей vtable. Таким образом, экземпляр не удаляет виртуальную таблицу, поскольку он ей не принадлежит.

Хранилище для vptr (не для той таблицы, на которую оно указывает) является частью экземпляра и удаляется вместе с экземпляром.

Во время строительства / уничтожения vptr устанавливается в vtable для каждого базового класса, когда они создаются. Отсутствие самого производного типа является причиной, по которой люди предупреждают о вызове виртуальных функций в конструкторе - возможно, вы не вызываете функцию, которую ожидали вызвать.

vptr становится непригодным после вызова последнего деструктора.

3 голосов
/ 08 декабря 2011

Может быть, здесь:

_free_dbg( pUserData, pHead->nBlockUse );

Vptr является частью объекта и не может быть удален отдельно.

...