Chinaunix首页 | 论坛 | 博客
  • 博客访问: 360501
  • 博文数量: 60
  • 博客积分: 15
  • 博客等级: 民兵
  • 技术积分: 1138
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-20 16:18
个人简介

最多140个字

文章分类

全部博文(60)

文章存档

2016年(1)

2015年(34)

2014年(25)

分类: C/C++

2014-05-10 14:34:36

C++中delete表达式执行的操作是:1,调用析构函数;2,释放对象内存(operator delete(...))。
如果父类的析构函数没有声明为virtual函数,且子类中至少存在一个virtual函数,此时将子类的对象地址赋值给父类指针。当对父类的指针执行delete操作时,会调用父类析构函数,然后在释放内存时(即delete表达式执行的操作的2,释放对象内存)出现崩溃。
然而如果子类中不存在一个virtual函数时,执行上面同样的操作就不会出现崩溃。
原因分析如下:

点击(此处)折叠或打开

  1. //已知本示例 父类的析构函数应声明为virtual函数。但是由于本程序不需要析构函数执行特殊的操作,所以delete父类指针pB同样可以释放内存,然而引起出乎意料的内//存释放异常。因此对本程序进行如下分析
  2. #include<iostream>
  3. #include stdio>
  1. using namespace std;

  2. class Base
  3. {
  4. public:
  5.  ~Base() {printf("\nBase::destructor.");}
  6. };

  7. class Derived: public Base
  8. {
  9.     virtual void show()
  10.     {
  11.         cout<<"show"<
  12.     }
  13. public:
  14.     ~Derived(){printf("\nDerived::destructor.");}
  15. };

  16. int main()
  17. {
  18.     Base* pB=NULL;
  19.     Derived *pD= new Derived;
  20.     pB=pD;//此时pD得到的是(unsigned char*)pD+4的地址,所以执行operator delete时会发生崩溃(因为此时把vptr的内存当成了待释放的内存块的大小)。
  21.     /*unsigned char *pC=(unsigned char*)pB;
  22.       pC=pC-4;
  23.       delete pC;//这样就可以释放new Derived分配的内存,而不会发生崩溃。
  24.     */
  25.     delete pB;
  26. }


其main函数对应的汇编代码如下(VC6.0):

点击(此处)折叠或打开

  1. int main()
  2. 23: {
  3. 00401060 push ebp
  4. 00401061 mov ebp,esp
  5. 00401063 push 0FFh
  6. 00401065 push offset __ehhandler$_main (00416a0b)
  7. 0040106A mov eax,fs:[00000000]
  8. 00401070 push eax
  9. 00401071 mov dword ptr fs:[0],esp
  10. 00401078 sub esp,64h
  11. 0040107B push ebx
  12. 0040107C push esi
  13. 0040107D push edi
  14. 0040107E lea edi,[ebp-70h]
  15. 00401081 mov ecx,19h
  16. 00401086 mov eax,0CCCCCCCCh
  17. 0040108B rep stos dword ptr [edi]

  18. 24:Base* pB=NULL;
  19. 0040108D mov dword ptr [ebp-10h],0
  20. 25: Derived *pD= new Derived;
  21. 00401094 push 4
  22. 00401096 call operator new (00403780)
  23. 0040109B add esp,4
  24. 0040109E mov dword ptr [ebp-1Ch],eax  //eax保存的是operator new(...)函数分配的内存的首地址。
  25. 004010A1 mov dword ptr [ebp-4],0
  26. 004010A8 cmp dword ptr [ebp-1Ch],0    //判断operator new(...)函数分配内存是否成功。
  27. 004010AC je main+5Bh (004010bb)
  28. 004010AE mov ecx,dword ptr [ebp-1Ch]   //调用Derived::Derived()函数,ecx保存的是内存指针。
  29. 004010B1 call @ILT+35(Derived::Derived) (00401028)
  30. 004010B6 mov dword ptr [ebp-28h],eax
  31. 004010B9 jmp main+62h (004010c2)
  32. 004010BB mov dword ptr [ebp-28h],0
  33. 004010C2 mov eax,dword ptr [ebp-28h]
  34. 004010C5 mov dword ptr [ebp-18h],eax
  35. 004010C8 mov dword ptr [ebp-4],0FFFFFFFFh
  36. 004010CF mov ecx,dword ptr [ebp-18h]
  37. 004010D2 mov dword ptr [ebp-14h],ecx
  38. 26: pB=pD;
  39. 004010D5 cmp dword ptr [ebp-14h],0
  40. 004010D9 je main+86h (004010e6)
  41. 004010DB mov edx,dword ptr [ebp-14h]
  42. 004010DE add edx,4
  43. 004010E1 mov dword ptr [ebp-2Ch],edx
  44. 004010E4 jmp main+8Dh (004010ed)
  45. 004010E6 mov dword ptr [ebp-2Ch],0
  46. 004010ED mov eax,dword ptr [ebp-2Ch]
  47. 004010F0 mov dword ptr [ebp-10h],eax   //pB=(unsinged char*)(pD)+4
  48. 27:
  49. 28: delete pB;
  50. 004010F3 mov ecx,dword ptr [ebp-10h]
  51. 004010F6 mov dword ptr [ebp-24h],ecx
  52. 004010F9 mov edx,dword ptr [ebp-24h]
  53. 004010FC mov dword ptr [ebp-20h],edx
  54. 004010FF cmp dword ptr [ebp-20h],0
  55. 00401103 je main+0B4h (00401114)
  56. 00401105 push 1
  57. 00401107 mov ecx,dword ptr [ebp-20h]
  58. 0040110A call @ILT+20(Base::`scalar deleting destructor
阅读(6702) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~