2

我正在处理一些奇怪的代码,对我来说它不是很好的代码。

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。

我期待在 delete []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. 如果我保留它的评论,一切都会失败。

即使我看到 disassemble ,在上述两种情况下也是不同的

/*****************************************************************/
/********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++ 的这个特性。

提前致谢。

星期六

4

2 回答 2

12

我在这里假设IP_IP_ADAPTER_INFO你的意思是 Windows 的IP_ADAPTER_INFO结构。即使不是,其要点是相同的:您的代码导致未定义的行为,这是编写它的人的错。立即修复它。

char您分配了一个with的数组new,但随后释放该内存,就好像它是一个IP_ADAPTER_INFO. C++ 不知道你在对它撒谎,所以它会尝试将你的char数组视为一个IP_ADAPTER_INFO数组,然后当它发现可怕的真相时可怕地死去。

现在,这有时会起作用,因为 VC++ 记录了足够多的关于已分配内存的信息,delete[]而不关心指针的类型,但这是邪恶的邪恶错误的错误的非法获取你的取回和拍摄代码

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

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

但即便如此,除非您需要在全局范围内保留该结构,否则它本身就指向糟糕的设计,您真的不应该在这里使用newand delete。你应该做一些更接近这个的事情:

IP_ADAPTER_INFO adapterInfo;
//DoSomethingToAdapterInfo(&adapterInfo);

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

如果您使用堆分配而不是堆栈分配有一些晦涩或独特的原因,那么您可能有理由这样做 - 但即便如此,强制new char[...]转换PIP_ADAPTER_INFO是不好的。

于 2010-09-28T04:57:49.607 回答
4

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

因此,您所看到的实际上是未定义的行为。

73) 这意味着不能使用 void* 类型的指针删除对象,因为没有 void 类型的对象。

于 2010-09-28T04:57:22.277 回答