背景
日常查看qq消息的时候,看到群里有位同学问到
在处理怎样让对象只能生成在堆上而不能生成在栈上的问题的时候,发现当私有化析构函数以后 , 为什么调用 operator new [] 会报错?
把问题翻译成代码
class A
{
friend class B;
public:
A();
private:
~ A();
};
A:: A()
{
cout << "A()" << endl;
}
A::~ A()
{
cout << "~A()" << endl;
}
int main()
{
A * test1 = new A[]; //使用new []会编译报错
A * test2 = new A; //但是使用 new 就没有问题
return 0;
}
原因
这个问题,我没有碰到过,但是有一本书《C++反汇编与逆向技术揭秘》,书上从汇编角度讲过 new[]/new 和delete[]/delete,也就是new/new[] 的时候汇编上面的表现是不一样的(可以配合着书本在本地IDE上反汇编看看),
下面的例子主要是为了说明 new和new[] 在汇编层面的区别
new的反汇编
new[]的反汇编
接下来解释一下两个汇编代码的意思
A * testA = new A;
压入待分配的类对象所需要的空间
00992A9D push 1
调用new函数进行分配空间
00992A9F call operator new (0991339h)
由于new函数是__cdecl调用类型,所以由调用者负责恢复堆栈平衡
00992AA4 add esp,4
将分配的地址存放在临时变量[ebp-0F8h]中
00992AA7 mov dword ptr [ebp-0F8h],eax
[ebp-4]保存申请堆空间的次数
00992AAD mov dword ptr [ebp-4],0
检测堆空间是否申请成功
00992AB4 cmp dword ptr [ebp-0F8h],0
如果申请失败的话,就跳过构造函数,跳到0x0992AD0h将存放this指针的临时变量赋值为0
00992ABB je main+70h (0992AD0h)
00992ABD mov ecx,dword ptr [ebp-0F8h] 00992AC3 call A::A (0991325h) 00992AC8 mov dword ptr [ebp-118h],eax 00992ACE jmp main+7Ah (0992ADAh) 00992AD0 mov dword ptr [ebp-118h],0 00992ADA mov eax,dword ptr [ebp-118h] 00992AE0 mov dword ptr [ebp-0ECh],eax 00992AE6 mov dword ptr [ebp-4],0FFFFFFFFh 00992AED mov ecx,dword ptr [ebp-0ECh] 00992AF3 mov dword ptr [testA],ecx
B * testB = new B[2];
00992AF6 push 6
00992AF8 call operator new[] (09913CAh)
00992AFD add esp,4
00992B00 mov dword ptr [ebp-110h],eax
00992B06 mov dword ptr [ebp-4],1
00992B0D cmp dword ptr [ebp-110h],0
00992B14 je main+0F0h (0992B50h)
00992B16 mov eax,dword ptr [ebp-110h]
00992B1C mov dword ptr [eax],2
00992B22 push offset B::~B (09911FEh)
00992B27 push offset B::B (0991456h)
00992B2C push 2
00992B2E push 1
00992B30 mov ecx,dword ptr [ebp-110h]
00992B36 add ecx,4
00992B39 push ecx
00992B3A call `eh vector constructor iterator' (0991168h)
00992B3F mov edx,dword ptr [ebp-110h]
00992B45 add edx,4
00992B48 mov dword ptr [ebp-118h],edx
00992B4E jmp main+0FAh (0992B5Ah)
00992B50 mov dword ptr [ebp-118h],0
00992B5A mov eax,dword ptr [ebp-118h]
00992B60 mov dword ptr [ebp-104h],eax
00992B66 mov dword ptr [ebp-4],0FFFFFFFFh
00992B6D mov ecx,dword ptr [ebp-104h]
00992B73 mov dword ptr [testB],ecx
参考:https://www.cnblogs.com/chaoguo1234/p/3213532.html