Когда оператор delete() в сборке удаляет указатель vptr?

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

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

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

Вот код сборки (void operator 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;

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


person Dean Seo    schedule 08.12.2011    source источник
comment
Я перечитал ваш вопрос несколько раз, и я все еще не совсем уверен, что понимаю, о чем вы спрашиваете...   -  person littleadv    schedule 08.12.2011
comment
Является ли это случаем чрезмерного обдумывания? Не могли бы вы опубликовать соответствующий код C++?   -  person Kerrek SB    schedule 08.12.2011
comment
@littleadv Извините, если я неясно выразился. Я просто хотел знать, где в этом коде сборки vptr (указатель на VTable) становится непригодным для использования (NULL)   -  person Dean Seo    schedule 08.12.2011
comment
@KerrekSB Единственная причина, по которой я пометил C++, заключается в том, что vtable и vptr определенно из C++. Но в любом случае спасибо за чтение и интерес к этому.   -  person Dean Seo    schedule 08.12.2011
comment
@YayCplusplus, а что заставляет вас думать, что это когда-либо происходит?   -  person littleadv    schedule 08.12.2011
comment
@littleadv Ну, мне просто очень любопытно, как vptr, указывающий на VTable, удаляется, и что ассемблерный код должен в какой-то момент удалить vptr, хотя я не совсем уверен, какая часть кода.   -  person Dean Seo    schedule 08.12.2011
comment
@YayCplusplus: vptr почти наверняка похож на другой член класса, только недоступен напрямую. Таким образом, он уничтожается вместе с объектом, как и любой другой член, без необходимости специального удаления.   -  person Mike Seymour    schedule 08.12.2011
comment
@YayCplusplus: Строго говоря, vtables — это метод программирования, используемый для реализации C++ — они не являются частью языка :-) С другой стороны, operator delete() является частью C++, поэтому мне было интересно, как это связано.   -  person Kerrek SB    schedule 08.12.2011
comment
@MikeSeymour О, не знал этого. Я думаю, что мое любопытство по этому поводу разрушилось. Спасибо!!   -  person Dean Seo    schedule 08.12.2011
comment
@KerrekSB О, понятно. Я думал, что С++ запустил vtables. Спасибо!   -  person Dean Seo    schedule 08.12.2011
comment
@YayCplusplus: люди знали, как создавать объекты на C задолго до C++. В некотором смысле, C++ был создан для того, чтобы систематизировать существующую практику в языке, если хотите.   -  person Kerrek SB    schedule 08.12.2011


Ответы (2)


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

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

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

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

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

person Cory Nelson    schedule 08.12.2011

Может здесь:

_free_dbg( pUserData, pHead->nBlockUse );

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

person Vbif    schedule 08.12.2011