我正在研究一些奇怪的代码,对我而言,这不是一段很好的代码。
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;
}
我所看到的:
即使我看到反汇编,但在上述两种情况下都是不同的
/*****************************************************************/
/********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 ++的这一功能。
提前致谢。
周六
答案 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;
但即便如此,除非你需要在全球范围内坚持这个结构,这本身就指向糟糕的设计,否则你真的不应该在这里使用new
和delete
。你应该做的更接近这个:
IP_ADAPTER_INFO adapterInfo;
//DoSomethingToAdapterInfo(&adapterInfo);
让C ++为您处理(在堆栈上)分配和删除。如果你需要返回结构,则返回它而不是指向它的指针(这样你的调用者就不必担心内存管理了。)
如果您使用堆分配而不是堆栈分配存在一些模糊或独特的原因,那么您可能有理由这样做 - 但即便如此,将new char[...]
强制转换为PIP_ADAPTER_INFO
也是错误的。
答案 1 :(得分:4)
$ 5.3.5 / 3 - “在第二种选择中 (删除数组)如果动态类型 要删除的对象不同于 它的静态类型,行为是 未定义。 73 )“
所以,你所看到的实际上是未定义的行为。
<子> 73) 这意味着无法使用void *类型的指针删除对象,因为没有void类型的对象。