Cast中C ++中Delete的行为

时间:2010-09-28 04:45:17

标签: c++ delete-operator

我正在研究一些奇怪的代码,对我而言,这不是一段很好的代码。

PIP_ADAPTER_INFO pAdapterInfo=(PIP_ADAPTER_INFO)new  
                               char[sizeof(IP_IP_ADAPTER_INFO)];

.
.
.
delete []pAdapterInfo;

此处PIP_ADAPTER_INFO是指向struct IP_IP_ADAPTER_INFO的指针,IP_IP_ADAPTER_INFO的大小为640.

我期待在删除[] pAdapterInfo调用时崩溃。但是没有崩溃。我写了一个小的 测试代码。

        class TestClass
        {

        public:
        /*  TestClass()
            {
            }
            ~TestClass()
            {
            }*/

        public:
            int array[10];
        };

        int main (int ac, char **av)

        {
            TestClass *myptr=(TestClass*) new char[10];
            delete []myptr;
            return 0;
        }

我所看到的:

  1. 如果我取消对c'tor和d'tor的评论,测试代码崩溃(断言失败)
  2. 如果我保持评论没有任何失败。
  3. 即使我看到反汇编,但在上述两种情况下都是不同的

    /*****************************************************************/
    /********Compiler provided c'tor and d'tor ***********************/
    /*****************************************************************/
    28:       TestClass *myptr=(TestClass*) new char[10];
    00401268   push        0Ah
    0040126A   call        operator new (004082d0)
    0040126F   add         esp,4
    00401272   mov         dword ptr [ebp-8],eax
    00401275   mov         eax,dword ptr [ebp-8]
    00401278   mov         dword ptr [ebp-4],eax
    29:       delete []myptr;
    0040127B   mov         ecx,dword ptr [ebp-4]
    0040127E   mov         dword ptr [ebp-0Ch],ecx
    00401281   mov         edx,dword ptr [ebp-0Ch]
    00401284   push        edx
    00401285   call        operator delete (004060d0)
    0040128A   add         esp,4
    30:
    /*****************************************************************/
    /********User provided c'tor and d'tor ***********************/
    /*****************************************************************/
    28:       TestClass *myptr=(TestClass*) new char[10];
    
    28:       TestClass *myptr=(TestClass*) new char[10];
    00401278   push        0Ah
    0040127A   call        operator new (004083e0)
    0040127F   add         esp,4
    00401282   mov         dword ptr [ebp-8],eax
    00401285   mov         eax,dword ptr [ebp-8]
    00401288   mov         dword ptr [ebp-4],eax
    29:       delete []myptr;
    0040128B   mov         ecx,dword ptr [ebp-4]
    0040128E   mov         dword ptr [ebp-10h],ecx
    00401291   mov         edx,dword ptr [ebp-10h]
    00401294   mov         dword ptr [ebp-0Ch],edx
    00401297   cmp         dword ptr [ebp-0Ch],0
    0040129B   je          main+4Ch (004012ac)
    0040129D   push        3
    0040129F   mov         ecx,dword ptr [ebp-0Ch]
    004012A2   call        @ILT+0(TestClass::`vector deleting destructor') (00401005)
    004012A7   mov         dword ptr [ebp-14h],eax
    004012AA   jmp         main+53h (004012b3)
    004012AC   mov         dword ptr [ebp-14h],0
    

    请帮助我学习C ++的这一功能。

    提前致谢。

    周六

2 个答案:

答案 0 :(得分:12)

我在这里假设IP_IP_ADAPTER_INFO你的意思是Windows'IP_ADAPTER_INFO结构。即使不是,这个的要点是一样的:你的代码导致了未定义的行为,而且是编写它的人的错。 立即修复。

您使用char分配了new数组,但随后将该内存释放为IP_ADAPTER_INFO数组。 C ++并不知道你是骗人的,所以它会尝试将你的char数组视为IP_ADAPTER_INFO数组,然后当它发现可怕的事实时就会死得很厉害。

现在,这有效有时因为VC ++记录了delete[]不关心指针类型的分配内存的足够信息,但这是邪恶的邪恶错误的非法采取后退拍摄代码

它可能适用于您的特定编译器,但这完全是一个侥幸。你应该这样做:

PIP_ADAPTER_INFO pAdapterInfo = new IP_ADAPTER_INFO;
//DoSomethingToAdapterInfo(pAdapterInfo);
delete pAdapterInfo;

但即便如此,除非你需要在全球范围内坚持这个结构,这本身就指向糟糕的设计,否则你真的不应该在这里使用newdelete。你应该做的更接近这个:

IP_ADAPTER_INFO adapterInfo;
//DoSomethingToAdapterInfo(&adapterInfo);

让C ++为您处理(在堆栈上)分配和删除。如果你需要返回结构,则返回它而不是指向它的指针(这样你的调用者就不必担心内存管理了。)

如果您使用堆分配而不是堆栈分配存在一些模糊或独特的原因,那么您可能有理由这样做 - 但即便如此,将new char[...]强制转换为PIP_ADAPTER_INFO也是错误的。

答案 1 :(得分:4)

  

$ 5.3.5 / 3 - “在第二种选择中   (删除数组)如果动态类型   要删除的对象不同于   它的静态类型,行为是   未定义。 73 )“

所以,你所看到的实际上是未定义的行为。

<子> 73) 这意味着无法使用void *类型的指针删除对象,因为没有void类型的对象。