Chinaunix首页 | 论坛 | 博客
  • 博客访问: 752527
  • 博文数量: 239
  • 博客积分: 60
  • 博客等级: 民兵
  • 技术积分: 1045
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-22 18:25
文章分类

全部博文(239)

文章存档

2019年(9)

2018年(64)

2017年(2)

2016年(26)

2015年(30)

2014年(41)

2013年(65)

2012年(2)

分类: C/C++

2013-01-29 17:56:53

    分析C++ new[]/delete[]调用与异常, 相比new/delete的调用与异常有相似之处, 但是细节的差别之处更需要注意.以下列出new/delete的标准形式 (来源:%20new/):

点击(此处)折叠或打开

  1. void* operator new (std::size_t size) throw (std::bad_alloc);
  2. void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw();
  3. void* operator new (std::size_t size, void* ptr) throw();
  4. void operator delete (void* ptr) throw ();
  5. void operator delete (void* ptr, const std::nothrow_t& nothrow_constant) throw();
  6. void operator delete (void* ptr, void* voidptr2) throw();
  7. void* operator new[] (std::size_t size) throw (std::bad_alloc);
  8. void* operator new[] (std::size_t size, const std::nothrow_t& nothrow_constant) throw();
  9. void* operator new[] (std::size_t size, void* ptr) throw();
  10. void operator delete[] (void* ptr) throw ();
  11. void operator delete[] (void* ptr, const std::nothrow_t& nothrow_constant) throw();
  12. void operator delete[] (void* ptr, void* voidptr2) throw();
  其中new/delete形式,前面的(一)(二)作了部分分析,这里我们使用示例代码情景分析new[]/delete[]. 在示例代码中, 用宏NEW_FAIL_OPERATOR来控制正常运行版本与异常版本, 当打开宏NEW_FAIL_OPERATOR时为异常示例版本,关闭宏NEW_FAIL_OPERATOR为正常运行版本;当为异常版本时,假设构造函数superClass在第二次构造的时候,抛出异常std::bad_alloc,这样更有利于代码情景分析. input number输入顺序为:1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10, 示例代码如下:

点击(此处)折叠或打开

  1. #include
  2. #include
  3. #include
  4. using namespace std;
  5. #define NEW_ARRAY
  6. //#define NEW_OPRATOR
  7. #define NEW_FAIL_OPERATOR
  8. //#define NEW_HANDLER
  9. static int g_exception = 0;
  10. struct myclass
  11. {
  12. myclass()
  13. {
  14. cout <<"myclass(), myclass constructed\n";
  15. #if defined(NEW_FAIL_OPERATOR)
  16. throw bad_alloc();
  17. #endif//NEW_FAIL_OPERATOR
  18. }
  19. ~myclass()
  20. {
  21. cout <<"~myclass(), myclass deconstructed\n";
  22. }
  23. virtual void testmyclass()
  24. {
  25. cout <<"myclass testmyclass called\n";
  26. }
  27. };
  28. class base
  29. {
  30. private:
  31. int mIndicate;
  32. public:
  33. base()
  34. {
  35. ++g_exception;
  36. mIndicate = g_exception;
  37. cout <<"base(), base constructed sizeof(*this)="<
  38. }
  39. return ;
  40. }
  41. void operator delete[] (void* p, const std::nothrow_t& nothrow_constant) throw()
  42. {
  43. try
  44. {
  45. cout <<"void operator delete[] (void* p, const std::nothrow_t& nothrow_constant) throw() called; strlen(p)="<
  46. free(p);
  47. }
  48. catch (...)
  49. {
  50. cout <<"void operator delete[] (void* p, const std::nothrow_t& nothrow_constant) throw() called; exception[unknown]"<
  51. }
  52. return ;
  53. }
  54. void operator delete[] (void* ptr, void* voidptr2) throw()
  55. {
  56. cout <<"void operator delete[] (void* ptr, void* voidptr2) throw() called; strlen(ptr)="<
  57. return ;
  58. }
  59. };
  60. //#if defined(NEW_ARRAY)
  61. int main(int argc, char* argv[])
  62. {
  63. #if defined(NEW_ARRAY)
  64. // uses first version:
  65. int * pa1 = new int[5];
  66. // uses second version:
  67. int * pa2 = new (nothrow) int[4];
  68. // uses third version:
  69. //pair pa3 = get_temporary_buffer(3);
  70. //new (pa3.first) myclass[3]; // calls constructors
  71. //return_temporary_buffer(pa3.first);// cut from %20new[]/
  72. int superClassSize = sizeof(superClass);
  73. superClass *pArryCon = NULL;
  74. int loop = true;
  75. while (loop)
  76. {
  77. size_t input = 0;
  78. cin.sync();
  79. cout.clear();
  80. cout<<"\n input %%u for input number:"<
  81. cin >> input;
  82. cout <<"input = "<
  83. try
  84. {
  85. switch(input)
  86. {
  87. case 1:
  88. {
  89. g_exception = 0;
  90. cout <<"paBase = (superClass *) operator new[](2 * superClassSize + 4);"<<" sizeof(superClass) = "<
  91. superClass * paBase1 = (superClass *) operator new[](2 * superClassSize + 4);
  92. superClass * pArryCon1 = new (paBase1) superClass[2];
  93. pArryCon1->~superClass();
  94. (pArryCon1 + 1)->~superClass();
  95. operator delete[](paBase1);
  96. paBase1 = NULL;
  97. cout <<"paBase1 = NULL;"<
  98. break;
  99. }
  100. case 2:
  101. {
  102. g_exception = 0;
  103. cout <<"paBase = new superClass[2];"<<" sizeof(superClass) = "<
  104. superClass * paBase2 = new superClass[2];
  105. delete [] paBase2;
  106. paBase2 = NULL;
  107. break;
  108. }
  109. case 3:
  110. {
  111. g_exception = 0;
  112. cout <<"paBase3 = (superClass *)superClass::operator new[](2 * superClassSize);"<<" sizeof(superClass) = "<
  113. superClass * paBase3 = (superClass *)superClass::operator new[](2 * superClassSize);
  114. superClass::operator delete[](paBase3);
  115. paBase3 = NULL;
  116. break;
  117. }
  118. case 4:
  119. {
  120. g_exception = 0;
  121. cout <<"const superClass * paBase4 = new (nothrow) const superClass[2];"<<" sizeof(superClass) = "<
  122. const superClass * paBase4 = new (nothrow) const superClass[2];
  123. delete [] paBase4;
  124. paBase4 = NULL;
  125. break;
  126. }
  127. case 5:
  128. {
  129. g_exception = 0;
  130. cout <<"superClass * paBase5 = new (nothrow) superClass[2];"<<" sizeof(superClass) = "<
  131. superClass * paBase5 = new (nothrow) superClass[2];
  132. delete [] paBase5;
  133. paBase5 = NULL;
  134. break;
  135. }
  136. case 6:
  137. {
  138. g_exception = 0;
  139. cout <<"superClass * paBase6 = (superClass *)operator new[](2 * superClassSize);"<<" sizeof(superClass) = "<
  140. superClass * paBase6 = (superClass *)operator new[](2 * superClassSize);
  141. operator delete[](paBase6);
  142. paBase6 = NULL;
  143. break;
  144. }
  145. case 7:
  146. {
  147. g_exception = 0;
  148. cout <<"superClass * paBase7 = (superClass *) operator new[](2 * superClassSize + 4);"<<" sizeof(superClass) = "<
  149. superClass * paBase7 = (superClass *) operator new[](2 * superClassSize + 4);
  150. const superClass * pArryCon7 = new (paBase7) const superClass[2];
  151. delete [] pArryCon7;
  152. paBase7 = NULL;
  153. break;
  154. }
  155. case 8:
  156. {
  157. g_exception = 0;
  158. cout <<"myclass * paBase8 = (myclass *) operator new[](2 * sizeof(myclass) + 4);"<<" sizeof(myclass) = "<
  159. myclass * paBase8 = (myclass *) operator new[](2 * sizeof(myclass) + 4);
  160. myclass * pArryCon8 = new (paBase8) myclass[2];
  161. delete [] pArryCon8;
  162. paBase8 = NULL;
  163. break;
  164. }
  165. case 9:
  166. {
  167. g_exception = 0;
  168. cout <<"paBase = new myclass[2];"<<" sizeof(myclass) = "<
  169. myclass * paBase9 = new myclass[2];
  170. delete [] paBase9;
  171. paBase9 = NULL;
  172. break;
  173. }
  174. case 10:
  175. {
  176. g_exception = 0;
  177. cout <<"paBase = (superClass *) operator new[](2 * superClassSize + 4);"<<" sizeof(superClass) = "<
  178. superClass * paBase10 = (superClass *)superClass::operator new[](2 * superClassSize + 4);
  179. superClass * pArryCon10 = new (paBase10) superClass[2];
  180. delete [] pArryCon10;
  181. paBase10 = NULL;
  182. break;
  183. }
  184. case 'q':
  185. loop = false;
  186. default:
  187. break;
  188. }
  189. }
  190. catch (...)
  191. {
  192. cout <<"exception when input = "<
  193. }
  194. }
  195. #endif//NEW_ARRAY
  196. return true;
  197. }
  示例new[]/delete[]在正常运行,即关闭宏NEW_FAIL_OPERATOR时的输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 1
  3. paBase = (superClass *) operator new[](2 * superClassSize + 4); sizeof(superClass) = 12
  4. void* operator new[](size_t s, void* object) throw() called; s=28 strlen(object)=33
  5. base(), base constructed sizeof(*this)=8; mIndicate = 1
  6. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  7. base(), base constructed sizeof(*this)=8; mIndicate = 2
  8. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  9. ~superClass(), superClass deconstructed; mIndicate = 1
  10. virtual ~base(), base deconstructed; mIndicate = 1
  11. ~superClass(), superClass deconstructed; mIndicate = 2
  12. virtual ~base(), base deconstructed; mIndicate = 2
  13. paBase1 = NULL;
  14. input %%u for input number:
  15. input = 2
  16. paBase = new superClass[2]; sizeof(superClass) = 12
  17. void* operator new[](size_t count) throw(std::bad_alloc) called; s=28
  18. base(), base constructed sizeof(*this)=8; mIndicate = 1
  19. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  20. base(), base constructed sizeof(*this)=8; mIndicate = 2
  21. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  22. ~superClass(), superClass deconstructed; mIndicate = 2
  23. virtual ~base(), base deconstructed; mIndicate = 2
  24. ~superClass(), superClass deconstructed; mIndicate = 1
  25. virtual ~base(), base deconstructed; mIndicate = 1
  26. void operator delete[] (void* ptr) throw () called; strlen(p)=1
  27. input %%u for input number:
  28. input = 3
  29. paBase3 = (superClass *)superClass::operator new[](2 * superClassSize); sizeof(superClass) = 12
  30. void* operator new[](size_t count) throw(std::bad_alloc) called; s=24
  31. void operator delete[] (void* ptr) throw () called; strlen(p)=33
  32. input %%u for input number:
  33. input = 4
  34. const superClass * paBase4 = new (nothrow) const superClass[2]; sizeof(superClass) = 12
  35. void* operator new[](size_t count, const std::nothrow_t&) throw() called ; s=28
  36. base(), base constructed sizeof(*this)=8; mIndicate = 1
  37. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  38. base(), base constructed sizeof(*this)=8; mIndicate = 2
  39. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  40. ~superClass(), superClass deconstructed; mIndicate = 2
  41. virtual ~base(), base deconstructed; mIndicate = 2
  42. ~superClass(), superClass deconstructed; mIndicate = 1
  43. virtual ~base(), base deconstructed; mIndicate = 1
  44. void operator delete[] (void* ptr) throw () called; strlen(p)=1
  45. input %%u for input number:
  46. input = 5
  47. superClass * paBase5 = new (nothrow) superClass[2]; sizeof(superClass) = 12
  48. void* operator new[](size_t count, const std::nothrow_t&) throw() called ; s=28
  49. base(), base constructed sizeof(*this)=8; mIndicate = 1
  50. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  51. base(), base constructed sizeof(*this)=8; mIndicate = 2
  52. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  53. ~superClass(), superClass deconstructed; mIndicate = 2
  54. virtual ~base(), base deconstructed; mIndicate = 2
  55. ~superClass(), superClass deconstructed; mIndicate = 1
  56. virtual ~base(), base deconstructed; mIndicate = 1
  57. void operator delete[] (void* ptr) throw () called; strlen(p)=1
  58. input %%u for input number:
  59. input = 6
  60. superClass * paBase6 = (superClass *)operator new[](2 * superClassSize); sizeof(superClass) = 12
  61. input %%u for input number:
  62. input = 7
  63. superClass * paBase7 = (superClass *) operator new[](2 * superClassSize + 4); sizeof(superClass) = 12
  64. void* operator new[](size_t s, void* object) throw() called; s=28 strlen(object)=33
  65. base(), base constructed sizeof(*this)=8; mIndicate = 1
  66. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  67. base(), base constructed sizeof(*this)=8; mIndicate = 2
  68. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  69. ~superClass(), superClass deconstructed; mIndicate = 2
  70. virtual ~base(), base deconstructed; mIndicate = 2
  71. ~superClass(), superClass deconstructed; mIndicate = 1
  72. virtual ~base(), base deconstructed; mIndicate = 1
  73. void operator delete[] (void* ptr) throw () called; strlen(p)=1
  74. input %%u for input number:
  75. input = 8
  76. myclass * paBase8 = (myclass *) operator new[](2 * sizeof(myclass) + 4); sizeof(myclass) = 4
  77. myclass(), myclass constructed
  78. myclass(), myclass constructed
  79. ~myclass(), myclass deconstructed
  80. ~myclass(), myclass deconstructed
  81. input %%u for input number:
  82. input = 9
  83. paBase = new myclass[2]; sizeof(myclass) = 4
  84. myclass(), myclass constructed
  85. myclass(), myclass constructed
  86. ~myclass(), myclass deconstructed
  87. ~myclass(), myclass deconstructed
  88. input %%u for input number:
  89. input = 10
  90. paBase = (superClass *) operator new[](2 * superClassSize + 4); sizeof(superClass) = 12
  91. void* operator new[](size_t count) throw(std::bad_alloc) called; s=28
  92. void* operator new[](size_t s, void* object) throw() called; s=28 strlen(object)=33
  93. base(), base constructed sizeof(*this)=8; mIndicate = 1
  94. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  95. base(), base constructed sizeof(*this)=8; mIndicate = 2
  96. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  97. ~superClass(), superClass deconstructed; mIndicate = 2
  98. virtual ~base(), base deconstructed; mIndicate = 2
  99. ~superClass(), superClass deconstructed; mIndicate = 1
  100. virtual ~base(), base deconstructed; mIndicate = 1
  101. void operator delete[] (void* ptr) throw () called; strlen(p)=1
  示例new[]/delete[]在构造函数第二次运行抛出异常时,即打开宏NEW_FAIL_OPERATOR时的输出结果: 

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 1
  3. paBase = (superClass *) operator new[](2 * superClassSize + 4); sizeof(superClass) = 12
  4. void* operator new[](size_t s, void* object) throw() called; s=28 strlen(object)=33
  5. base(), base constructed sizeof(*this)=8; mIndicate = 1
  6. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  7. base(), base constructed sizeof(*this)=8; mIndicate = 2
  8. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  9. virtual ~base(), base deconstructed; mIndicate = 2
  10. ~superClass(), superClass deconstructed; mIndicate = 1
  11. virtual ~base(), base deconstructed; mIndicate = 1
  12. void operator delete[] (void* ptr, void* voidptr2) throw() called; strlen(ptr)=1;strlen(voidptr2)=1
  13. exception when input = 1 next sequence
  14. input %%u for input number:
  15. input = 2
  16. paBase = new superClass[2]; sizeof(superClass) = 12
  17. void* operator new[](size_t count) throw(std::bad_alloc) called; s=28
  18. base(), base constructed sizeof(*this)=8; mIndicate = 1
  19. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  20. base(), base constructed sizeof(*this)=8; mIndicate = 2
  21. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  22. virtual ~base(), base deconstructed; mIndicate = 2
  23. ~superClass(), superClass deconstructed; mIndicate = 1
  24. virtual ~base(), base deconstructed; mIndicate = 1
  25. void operator delete[] (void* ptr) throw () called; strlen(p)=1
  26. exception when input = 2 next sequence
  27. input %%u for input number:
  28. input = 3
  29. paBase3 = (superClass *)superClass::operator new[](2 * superClassSize); sizeof(superClass) = 12
  30. void* operator new[](size_t count) throw(std::bad_alloc) called; s=24
  31. void operator delete[] (void* ptr) throw () called; strlen(p)=33
  32. input %%u for input number:
  33. input = 4
  34. const superClass * paBase4 = new (nothrow) const superClass[2]; sizeof(superClass) = 12
  35. void* operator new[](size_t count, const std::nothrow_t&) throw() called ; s=28
  36. base(), base constructed sizeof(*this)=8; mIndicate = 1
  37. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  38. base(), base constructed sizeof(*this)=8; mIndicate = 2
  39. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  40. virtual ~base(), base deconstructed; mIndicate = 2
  41. ~superClass(), superClass deconstructed; mIndicate = 1
  42. virtual ~base(), base deconstructed; mIndicate = 1
  43. void operator delete[] (void* p, const std::nothrow_t& nothrow_constant) throw() called; strlen(p)=1
  44. exception when input = 4 next sequence
  45. input %%u for input number:
  46. input = 5
  47. superClass * paBase5 = new (nothrow) superClass[2]; sizeof(superClass) = 12
  48. void* operator new[](size_t count, const std::nothrow_t&) throw() called ; s=28
  49. base(), base constructed sizeof(*this)=8; mIndicate = 1
  50. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  51. base(), base constructed sizeof(*this)=8; mIndicate = 2
  52. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  53. virtual ~base(), base deconstructed; mIndicate = 2
  54. ~superClass(), superClass deconstructed; mIndicate = 1
  55. virtual ~base(), base deconstructed; mIndicate = 1
  56. void operator delete[] (void* p, const std::nothrow_t& nothrow_constant) throw() called; strlen(p)=1
  57. exception when input = 5 next sequence
  58. input %%u for input number:
  59. input = 6
  60. superClass * paBase6 = (superClass *)operator new[](2 * superClassSize); sizeof(superClass) = 12
  61. input %%u for input number:
  62. input = 7
  63. superClass * paBase7 = (superClass *) operator new[](2 * superClassSize + 4); sizeof(superClass) = 12
  64. void* operator new[](size_t s, void* object) throw() called; s=28 strlen(object)=33
  65. base(), base constructed sizeof(*this)=8; mIndicate = 1
  66. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  67. base(), base constructed sizeof(*this)=8; mIndicate = 2
  68. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  69. virtual ~base(), base deconstructed; mIndicate = 2
  70. ~superClass(), superClass deconstructed; mIndicate = 1
  71. virtual ~base(), base deconstructed; mIndicate = 1
  72. void operator delete[] (void* ptr, void* voidptr2) throw() called; strlen(ptr)=1;strlen(voidptr2)=1
  73. exception when input = 7 next sequence
  74. input %%u for input number:
  75. input = 8
  76. myclass * paBase8 = (myclass *) operator new[](2 * sizeof(myclass) + 4); sizeof(myclass) = 4
  77. myclass(), myclass constructed
  78. exception when input = 8 next sequence
  79. input %%u for input number:
  80. input = 9
  81. paBase = new myclass[2]; sizeof(myclass) = 4
  82. myclass(), myclass constructed
  83. exception when input = 9 next sequence
  84. input %%u for input number:
  85. input = 10
  86. paBase = (superClass *) operator new[](2 * superClassSize + 4); sizeof(superClass) = 12
  87. void* operator new[](size_t count) throw(std::bad_alloc) called; s=28
  88. void* operator new[](size_t s, void* object) throw() called; s=28 strlen(object)=33
  89. base(), base constructed sizeof(*this)=8; mIndicate = 1
  90. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  91. base(), base constructed sizeof(*this)=8; mIndicate = 2
  92. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  93. virtual ~base(), base deconstructed; mIndicate = 2
  94. ~superClass(), superClass deconstructed; mIndicate = 1
  95. virtual ~base(), base deconstructed; mIndicate = 1
  96. void operator delete[] (void* ptr, void* voidptr2) throw() called; strlen(ptr)=1;strlen(voidptr2)=1
  97. exception when input = 10 next sequence
根据输出结果我们进行分类分析:
(1)形式operator new[](size), new (pAddressClass[Num]和operator delete[](pAddress)的分析.其中, Class对new[]和delete[]进行了操作符重载. 对应示例中的代码为: 

点击(此处)折叠或打开

  1. g_exception = 0;
  2. cout <<"paBase = (superClass *) operator new[](2 * superClassSize + 4);"<<" sizeof(superClass) = "<
  3. superClass * paBase1 = (superClass *) operator new[](2 * superClassSize + 4);
  4. superClass * pArryCon1 = new (paBase1) superClass[2];
  5. pArryCon1->~superClass();
  6. (pArryCon1 + 1)->~superClass();
  7. operator delete[](paBase1);
  8. paBase1 = NULL;
  9. cout <<"paBase1 = NULL;"<
  10. break;
  示例在正常运行,即关闭宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. paBase = (superClass *) operator new[](2 * superClassSize + 4); sizeof(superClass) = 12
  2. void* operator new[](size_t s, void* object) throw() called; s=28 strlen(object)=33
  3. base(), base constructed sizeof(*this)=8; mIndicate = 1
  4. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  5. base(), base constructed sizeof(*this)=8; mIndicate = 2
  6. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  7. ~superClass(), superClass deconstructed; mIndicate = 1
  8. virtual ~base(), base deconstructed; mIndicate = 1
  9. ~superClass(), superClass deconstructed; mIndicate = 2
  10. virtual ~base(), base deconstructed; mIndicate = 2
  11. paBase1 = NULL;
  示例在构造函数第二次运行抛出异常时,即打开宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. paBase = (superClass *) operator new[](2 * superClassSize + 4); sizeof(superClass) = 12
  2. void* operator new[](size_t s, void* object) throw() called; s=28 strlen(object)=33
  3. base(), base constructed sizeof(*this)=8; mIndicate = 1
  4. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  5. base(), base constructed sizeof(*this)=8; mIndicate = 2
  6. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  7. virtual ~base(), base deconstructed; mIndicate = 2
  8. ~superClass(), superClass deconstructed; mIndicate = 1
  9. virtual ~base(), base deconstructed; mIndicate = 1
  10. void operator delete[] (void* ptr, void* voidptr2) throw() called; strlen(ptr)=1;strlen(voidptr2)=1
  11. exception when input = 1 next sequence
  根据结果分析,示例(1)的代码在异常版本中执行到程序superClass * pArryCon1 = new (paBase1) superClass[2]就异常不在执行后序的代码.

    i.代码superClass * paBase1 = (superClass *) operator new[](2 * superClassSize + 4)    ->  调用库函数void *__CRTDECL operator new[](size_t count) _THROW1(std::bad_alloc), 并且正常和异常版本都没有调用superClass的构造函数;特别注意2 * superClassSize + 4中的 4 = sizeof(int *), 表示在使用 operator new[]需要多分配一个指针内存, 否则在释放内存时将导致栈异常.

    ii.代码superClass * pArryCon1 = new (paBase1) superClass[2]  ->  先调用superClass类的void* operator new[](size_t s, void* object) throw(), 再调用superClass[0]的构造函数, 最后调用superClass[1]的构造函数;

      分析示例(1)的异常版本,我们前面做了假设, 在superClass[1]的构造函数superClass()中抛出异常,即在superClass异常抛出后, new (pAddress) Class[NUm]执行了superClass[1]的virtual ~base(), 其后执行superClass[0]的~superClass(), 在执行superClass[0]的virtual ~base()函数, 最后执行superClass类的void operator delete[] (void* ptr, void* voidptr2) throw(), 并退出不执行示例(1)其后序代码,造成了内存的泄漏, 需要注意并此处没有调用superClass[1]的~superClass(), 因为对象没有构造成功.这告诉我们,内存使用在没有非常有把握情况下, 尽可能使用原来new[]/delete[]语义, 否则容易造成内存操作失误.

   iii.代码pArryCon1->~superClass()  ->  执行superClass[0]的~superClass(),在执行superClass[0]的virtual ~base().

   iv.代码pArryCon1->~superClass()  ->  执行superClass[1]的~superClass(),在执行superClass[1]的virtual ~base(), 对比(i)(iii) 看出调用的都是类的析构函数, 并且析构函数的执行顺序相似.

    v.代码operator delete[](paBase1) ->  调用库函数void operator delete[]( void * p ), 请区别因为此处没有调用superClass类的void operator delete[] (void* p) throw (); 如果将operator delete[](paBase1)改成operator delete[](pArryCon1), 将发生栈非法, 用编译器查看到paBase1只是内存, pArryCon1含有虚表即被new被放置过.

    示例(1)在正常调用与发生异常情况下, 产生了不同结果, 同时在异常发生时造成了内存泄漏, superClass类的void operator delete[] (void* ptr, void* voidptr2) throw()用于编译器在new放置式异常的调用函数.   

(2)形式Class pAddress = new Class[Num]和delete[](pAddress)的分析.其中Class重载了new[]/delete[]操作符对应示例中的代码为:

点击(此处)折叠或打开

  1. cout <<"paBase = new superClass[2];"<<" sizeof(superClass) = "<
  2. superClass * paBase2 = new superClass[2];
  3. delete [] paBase2;
  4. paBase2 = NULL;
  示例在正常运行,即关闭宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. paBase = new superClass[2]; sizeof(superClass) = 12
  2. void* operator new[](size_t count) throw(std::bad_alloc) called; s=28
  3. base(), base constructed sizeof(*this)=8; mIndicate = 1
  4. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  5. base(), base constructed sizeof(*this)=8; mIndicate = 2
  6. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  7. ~superClass(), superClass deconstructed; mIndicate = 2
  8. virtual ~base(), base deconstructed; mIndicate = 2
  9. ~superClass(), superClass deconstructed; mIndicate = 1
  10. virtual ~base(), base deconstructed; mIndicate = 1
  11. void operator delete[] (void* ptr) throw () called; strlen(p)=1
  示例在构造函数第二次运行抛出异常时,即打开宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. paBase = new superClass[2]; sizeof(superClass) = 12
  2. void* operator new[](size_t count) throw(std::bad_alloc) called; s=28
  3. base(), base constructed sizeof(*this)=8; mIndicate = 1
  4. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  5. base(), base constructed sizeof(*this)=8; mIndicate = 2
  6. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  7. virtual ~base(), base deconstructed; mIndicate = 2
  8. ~superClass(), superClass deconstructed; mIndicate = 1
  9. virtual ~base(), base deconstructed; mIndicate = 1
  10. void operator delete[] (void* ptr) throw () called; strlen(p)=1
  11. exception when input = 2 next sequence
    根据结果分析,形式new Class[Num]和delete[](pAddress)在new Class[Num]是否发生异常产生不同的行为, 若在语句superClass * paBase2 = new superClass[2]发生异常,将进行异常处理后退出. 我们进行代码语句分析:

    i. 语句superClass * paBase2 = new superClass[2]  ->  先调用superClass类的void* operator new[](size_t count) throw(std::bad_alloc), 在调用superClass[0]的构造函数,最后调用superClass[1]的构造函数. 顺序是先申请内存,在调用对象构造函数.

      分析示例(2)的异常版本,我们前面做了假设, 在superClass[1]的构造函数superClass()中抛出异常,即在superClass异常抛出后,语句superClass * paBase2 = new superClass[2]先执行了superClass[1]的virtual ~base(), 其后执行superClass[0]的~superClass(), 在执行superClass[0]的virtual ~base()函数, 最后执行superClass类的void operator delete[] (void* ptr) throw (),  而不是执行superClass类的void operator delete[] (void* ptr, void* voidptr2) throw(); 需要注意此处没有调用superClass[1]的~superClass(),  因为对象没有构造成功. new[]/delete[]相互对应, 即便异常也没有造成内存泄漏, 这就为什么操作符重载new[]也要同时重载对应的delete[]. 

    ii.语句delete [] paBase2  -> 先执行superClass[1]的~superClass();在执行superClass[1]的virtual ~base(); 其后执行superClass[0]的~superClass(); 然后在执行superClass[0]的virtual ~base(); 最后执行superClass类的void operator delete[] (void* ptr) throw ().执行的函数和执行的顺序是非常重要的,我们要注意.

    示例(2)分析知道new[]/delete[]是需要要么一起被重载,要么都不重载, 数组对象追寻过程中,有一个未创建成功, 数组中其他创建成功的对象也会被析构. 数组对象构造按数组内成员的顺序从小到大,析构则从大到小. 最后我们需要知道, new const Class[num]正常与异常版本的调用行为与new Class[num]是一样的, 只是const关键字需要注意的new const Class[num]也是一样要注意.如const Class *pAddr = new const Class[num]的写法与操作.请对比区别示例(4)的行为.

(3)形式Class::operator new[](size)和Class::operator delete[](pAddress)的分析;其中Class对new[]/delete[]进行了重载. 对应示例中的代码为:

点击(此处)折叠或打开

  1. cout <<"paBase3 = (superClass *)superClass::operator new[](2 * superClassSize);"<<" sizeof(superClass) = "<
  2. superClass * paBase3 = (superClass *)superClass::operator new[](2 * superClassSize);
  3. superClass::operator delete[](paBase3);
  4. paBase3 = NULL;
  示例在正常运行,即关闭宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. paBase3 = (superClass *)superClass::operator new[](2 * superClassSize); sizeof(superClass) = 12
  2. void* operator new[](size_t count) throw(std::bad_alloc) called; s=24
  3. void operator delete[] (void* ptr) throw () called; strlen(p)=33
  示例在构造函数第二次运行抛出异常时,即打开宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. paBase3 = (superClass *)superClass::operator new[](2 * superClassSize); sizeof(superClass) = 12
  2. void* operator new[](size_t count) throw(std::bad_alloc) called; s=24
  3. void operator delete[] (void* ptr) throw () called; strlen(p)=33
  根据结果我们进行语句分析:

    i. 语句superClass * paBase3 = (superClass *)superClass::operator new[](2 * superClassSize)   ->  只有调用superClass类的void* operator new[](size_t count) throw(std::bad_alloc),没有调用对象构造函数.

    ii.语句superClass::operator delete[](paBase3)  ->  只有调用superClass类的void operator delete[] (void* ptr) throw (), 没有调用对象析构函数.

    示例(3)看出, 当用户调用operator new[]/operator delete[]时, 只是类似普通的static类成员函数, 不会调用类的构造与析构函数.

(4)形式new (nothrow) const  Class[Num]delete[] (pAddress)的分析.其中Class对new[]/delete[]进行了重载. 对应示例中的代码为:

点击(此处)折叠或打开

  1. cout <<"const superClass * paBase4 = new (nothrow) const superClass[2];"<<" sizeof(superClass) = "<
  2. const superClass * paBase4 = new (nothrow) const superClass[2];
  3. delete [] paBase4;
  4. paBase4 = NULL;
  示例在正常运行,即关闭宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 4
  3. const superClass * paBase4 = new (nothrow) const superClass[2]; sizeof(superClass) = 12
  4. void* operator new[](size_t count, const std::nothrow_t&) throw() called ; s=28
  5. base(), base constructed sizeof(*this)=8; mIndicate = 1
  6. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  7. base(), base constructed sizeof(*this)=8; mIndicate = 2
  8. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  9. ~superClass(), superClass deconstructed; mIndicate = 2
  10. virtual ~base(), base deconstructed; mIndicate = 2
  11. ~superClass(), superClass deconstructed; mIndicate = 1
  12. virtual ~base(), base deconstructed; mIndicate = 1
  13. void operator delete[] (void* ptr) throw () called; strlen(p)=1
  示例在构造函数第二次运行抛出异常时,即打开宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 4
  3. const superClass * paBase4 = new (nothrow) const superClass[2]; sizeof(superClass) = 12
  4. void* operator new[](size_t count, const std::nothrow_t&) throw() called ; s=28
  5. base(), base constructed sizeof(*this)=8; mIndicate = 1
  6. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  7. base(), base constructed sizeof(*this)=8; mIndicate = 2
  8. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  9. virtual ~base(), base deconstructed; mIndicate = 2
  10. ~superClass(), superClass deconstructed; mIndicate = 1
  11. virtual ~base(), base deconstructed; mIndicate = 1
  12. void operator delete[] (void* p, const std::nothrow_t& nothrow_constant) throw() called; strlen(p)=1
  13. exception when input = 4 next sequence
  根据示例(4)结果, new[]其实有几种写法, 更可怕的是, 还可以有const类型的.在示例(4)异常版本中,const superClass * paBase4 = new (nothrow) const superClass[2]执行后将退出. 我们进行语句分析:

    i.语句const superClass * paBase4 = new (nothrow) const superClass[2]  ->  首先调用superClass类的void* operator new[](size_t count, const std::nothrow_t&) throw(), 在调用superClass[0]的构造函数,最后调用superClass[1]的构造函数. 注意此处没有调用superClass类的void* operator new[](size_t count) throw, 请区别于new Class[Num]形式.

      分析示例(4)的异常版本,我们前面做了假设, 在superClass[1]的const superClass * paBase4 = new (nothrow) const superClass[2] 中抛出异常,即在superClass异常抛出后,语句const superClass * paBase4 = new (nothrow) const superClass[2]在执行superClass()后, 执行了superClass[1]的virtual ~base(), 其后执行superClass[0]的~superClass(), 在执行superClass[0]的virtual ~base()函数, 最后执行superClass类的void operator delete[] (void* p, const std::nothrow_t& nothrow_constant) throw(), 不是void operator delete[] (void* ptr) throw (),  也不是superClass类的void operator delete[] (void* ptr, void* voidptr2) throw(); 需要注意此处没有调用superClass[1]的~superClass(),  因为对象没有构造成功.

    ii.语句delete [] paBase4  ->  示例(2) ii.相似.

    示例(4)让我们知道,  const 类型是可以new (nothrow) const Class[Num]出来的, 并且调用的operator new也是与new Class[Num]不一样,发生异常后, 编译器调用的处理operator delete[]也不一样.其中类中的成员函数void* operator new[](size_t count, const std::nothrow_t&) throw(),  void operator delete[] (void* ptr) throw ()和void operator delete[] (void* p, const std::nothrow_t& nothrow_constant) throw()都与new 的nothrow相关.

(5)形式new const  Class[Num]delete[] (pAddress)的分析.其中Class对new[]/delete[]进行了重载.对应示例中的代码为:

点击(此处)折叠或打开

  1. cout <<"superClass * paBase5 = new (nothrow) superClass[2];"<<" sizeof(superClass) = "<
  2. superClass * paBase5 = new (nothrow) superClass[2];
  3. delete [] paBase5;
  4. paBase5 = NULL;
  示例在正常运行,即关闭宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 5
  3. superClass * paBase5 = new (nothrow) superClass[2]; sizeof(superClass) = 12
  4. void* operator new[](size_t count, const std::nothrow_t&) throw() called ; s=28
  5. base(), base constructed sizeof(*this)=8; mIndicate = 1
  6. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  7. base(), base constructed sizeof(*this)=8; mIndicate = 2
  8. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  9. ~superClass(), superClass deconstructed; mIndicate = 2
  10. virtual ~base(), base deconstructed; mIndicate = 2
  11. ~superClass(), superClass deconstructed; mIndicate = 1
  12. virtual ~base(), base deconstructed; mIndicate = 1
  13. void operator delete[] (void* ptr) throw () called; strlen(p)=1
  示例在构造函数第二次运行抛出异常时,即打开宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 5
  3. superClass * paBase5 = new (nothrow) superClass[2]; sizeof(superClass) = 12
  4. void* operator new[](size_t count, const std::nothrow_t&) throw() called ; s=28
  5. base(), base constructed sizeof(*this)=8; mIndicate = 1
  6. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  7. base(), base constructed sizeof(*this)=8; mIndicate = 2
  8. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  9. virtual ~base(), base deconstructed; mIndicate = 2
  10. ~superClass(), superClass deconstructed; mIndicate = 1
  11. virtual ~base(), base deconstructed; mIndicate = 1
  12. void operator delete[] (void* p, const std::nothrow_t& nothrow_constant) throw() called; strlen(p)=1
  13. exception when input = 5 next sequence
  根据示例(5)结果分析, new (nothrow) Class[num] 与new (nothrow) const Class[num]调用的函数在正常与异常版本相似. 语句superClass * paBase5 = new (nothrow) superClass[2]行为与示例(4)i. 相似; delete [] paBase5与示例(4)ii.相似.  这真是让人抓狂.. 

(6)形式operator new[](sizeof(Class)*num)和operator delete[](pAddress)的分析.其中Class对new[]/delete[]进行了重载.对应示例中的代码为:

点击(此处)折叠或打开

  1. cout <<"superClass * paBase6 = (superClass *)operator new[](2 * superClassSize);"<<" sizeof(superClass) = "<
  2. superClass * paBase6 = (superClass *)operator new[](2 * superClassSize);
  3. operator delete[](paBase6);
  4. paBase6 = NULL;
  示例在正常运行,即关闭宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 6
  3. superClass * paBase6 = (superClass *)operator new[](2 * superClassSize); sizeof(superClass) = 12
  示例在构造函数第二次运行抛出异常时,即打开宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 6
  3. superClass * paBase6 = (superClass *)operator new[](2 * superClassSize); sizeof(superClass) = 12
  根据示例(6)结果分析,superClass * paBase6 = (superClass *)operator new[](2 * superClassSize)  -> 调用库函数void *__CRTDECL operator new[](size_t count) _THROW1(std::bad_alloc), 并且不调用类的构造函数;  operator delete[](paBase6)  ->  调用库函数void operator delete[]( void * p ),并且不调用类的析构函数. 说明当用户使用operator new[]/delete[]时, 只是当成类似普通函数或者成员函数;与示例(3)对比发现, 要调用类的operator new/operator delete需要加命名空间.

(7)形式operator new[](size), new (pAddress)  const Class[Num]和delete [] (pAddress)的分析.其中Class对new[]/delete[]进行了重载.对应示例中的代码为:

点击(此处)折叠或打开

  1. cout <<"superClass * paBase7 = (superClass *) operator new[](2 * superClassSize + 4);"<<" sizeof(superClass) = "<
  2. superClass * paBase7 = (superClass *) operator new[](2 * superClassSize + 4);
  3. const superClass * pArryCon7 = new (paBase7) const superClass[2];
  4. delete [] pArryCon7;
  5. paBase7 = NULL;
  示例在正常运行,即关闭宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 7
  3. superClass * paBase7 = (superClass *) operator new[](2 * superClassSize + 4); sizeof(superClass) = 12
  4. void* operator new[](size_t s, void* object) throw() called; s=28 strlen(object)=33
  5. base(), base constructed sizeof(*this)=8; mIndicate = 1
  6. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  7. base(), base constructed sizeof(*this)=8; mIndicate = 2
  8. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  9. ~superClass(), superClass deconstructed; mIndicate = 2
  10. virtual ~base(), base deconstructed; mIndicate = 2
  11. ~superClass(), superClass deconstructed; mIndicate = 1
  12. virtual ~base(), base deconstructed; mIndicate = 1
  13. void operator delete[] (void* ptr) throw () called; strlen(p)=1
  示例在构造函数第二次运行抛出异常时,即打开宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 7
  3. superClass * paBase7 = (superClass *) operator new[](2 * superClassSize + 4); sizeof(superClass) = 12
  4. void* operator new[](size_t s, void* object) throw() called; s=28 strlen(object)=33
  5. base(), base constructed sizeof(*this)=8; mIndicate = 1
  6. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  7. base(), base constructed sizeof(*this)=8; mIndicate = 2
  8. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  9. virtual ~base(), base deconstructed; mIndicate = 2
  10. ~superClass(), superClass deconstructed; mIndicate = 1
  11. virtual ~base(), base deconstructed; mIndicate = 1
  12. void operator delete[] (void* ptr, void* voidptr2) throw() called; strlen(ptr)=1;strlen(voidptr2)=1
  13. exception when input = 7 next sequence
  根据示例(7)结果分析,new (pAddress) Class[num]与new (pAddress)  const Class[num]正常与异常版本的调用函数都相似,  operator new[]的两种放置式写法行为类似, 但是需要区别关键字const相关的行为.

(8)形式operator new[](size), new (pAddress)  Class[Num]和delete [] (pAddress)的分析.其中Class没有对new[]/delete[]进行重载, 对应示例中的代码为:

点击(此处)折叠或打开

  1. cout <<"myclass * paBase8 = (myclass *) operator new[](2 * sizeof(myclass) + 4);"<<" sizeof(myclass) = "<
  2. myclass * paBase8 = (myclass *) operator new[](2 * sizeof(myclass) + 4);
  3. myclass * pArryCon8 = new (paBase8) myclass[2];
  4. delete [] pArryCon8;
  5. paBase8 = NULL;
  示例在正常运行,即关闭宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 8
  3. myclass * paBase8 = (myclass *) operator new[](2 * sizeof(myclass) + 4); sizeof(myclass) = 4
  4. myclass(), myclass constructed
  5. myclass(), myclass constructed
  6. ~myclass(), myclass deconstructed
  7. ~myclass(), myclass deconstructed
  示例在构造函数第二次运行抛出异常时,即打开宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 8
  3. myclass * paBase8 = (myclass *) operator new[](2 * sizeof(myclass) + 4); sizeof(myclass) = 4
  4. myclass(), myclass constructed
  5. exception when input = 8 next sequence
    根据示例(8)结果分析, new放置式形式new (pAddress)  Class[Num]在Class是否重载operator new[]/operator delete[]产生了不同的行为.在示例(8)异常版本中, myclass * pArryCon8 = new (paBase8) myclass[2]抛出异常退出.

    i.语句myclass * paBase8 = (myclass *) operator new[](2 * sizeof(myclass) + 4 ->  调用库函数void *__CRTDECL operator new[](size_t count) _THROW1(std::bad_alloc), 不调用类的构造函数.其中 4 = sizeof(int *).

    ii.语句myclass * pArryCon8 = new (paBase8) myclass[2]  ->  先调用库函数inline void *__CRTDECL operator new[](size_t, void *_Where) _THROW0(); 在调用myclass[0]的构造函数;最后在调用myclass[1]的构造函数.

      在示例(8)异常版本中, myclass * pArryCon8 = new (paBase8) myclass[2]   ->  先调用库函数inline void *__CRTDECL operator new[](size_t, void *_Where) _THROW0(); 在调用myclass[0]的构造函数, 然后抛出std::bad_alloc异常, 最后调用库函数inline void __CRTDECL operator delete[](void *, void *) _THROW0().  

     iii.语句delete [] pArryCon8  ->  先调用myclass[1]析构函数,在调用myclass[0]析构函, 最后调用库函数void operator delete[]( void * p ).

    示例(8)是在没有重载operator new[]/operator delete[]情况下的new []的放置式行为,是平时我们使用new []的放置式行为, 在使用operator new[](2 * sizeof(myclass) + 4)后,  如果放置式发生异常, 将产生内存泄漏. 这也是我们平时使用放置式需要注意的.

(9)形式new Class[num]delete [(pAddress)的分析.其中Class没有对new[]/delete[]进行重载,对应示例中的代码为:

点击(此处)折叠或打开

  1. cout <<"paBase = new myclass[2];"<<" sizeof(myclass) = "<
  2. myclass * paBase9 = new myclass[2];
  3. delete [] paBase9;
  4. paBase9 = NULL;
  示例在正常运行,即关闭宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 9
  3. paBase = new myclass[2]; sizeof(myclass) = 4
  4. myclass(), myclass constructed
  5. myclass(), myclass constructed
  6. ~myclass(), myclass deconstructed
  7. ~myclass(), myclass deconstructed
  示例在构造函数第二次运行抛出异常时,即打开宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 9
  3. paBase = new myclass[2]; sizeof(myclass) = 4
  4. myclass(), myclass constructed
  5. exception when input = 9 next sequence
    示例(9)是我们大家平时最经常用的形式,最有可能在new class[num]时候抛出异常.我们进行代码分析:

   i.语句myclass * paBase9 = new myclass[2]    ->  先调用库函数void *__CRTDECL operator new[](size_t count) _THROW1(std::bad_alloc),在调用myclass[0]的构造函数, 最后调用myclass[1]的构造函数.

      在示例(9)的异常版本中,myclass * paBase9 = new myclass[2]  -> 先调用库函数void *__CRTDECL operator new[](size_t count) _THROW1(std::bad_alloc),在调用myclass[0]的构造函数,当myclass[0]的构造函数抛出异常后, 调用库函void operator delete[]( void * p );然后退出.

    ii.语句 delete [] paBase9 ->  先调用myclass[1]的析构函数, 在调用myclass[0]的构造函数, 最后调用库函数void operator delete[]( void * p ); 

    在示例(9)展示了平时C++ new []的用法和调用库函数的简单过程, 展示为什么new不成功不会造成内存泄漏,希望我们能知其然知其所以然.

(10)形式operator new[](size), new (pAddress)  Class[Num]和operator delete[](pAddress)的分析.对应示例中的代码为:

点击(此处)折叠或打开

  1. cout <<"paBase = (superClass *) operator new[](2 * superClassSize + 4);"<<" sizeof(superClass) = "<
  2. superClass * paBase10 = (superClass *)superClass::operator new[](2 * superClassSize + 4);
  3. superClass * pArryCon10 = new (paBase10) superClass[2];
  4. delete [] pArryCon10;
  5. paBase10 = NULL;
  示例在正常运行,即关闭宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 10
  3. paBase = (superClass *) operator new[](2 * superClassSize + 4); sizeof(superClass) = 12
  4. void* operator new[](size_t count) throw(std::bad_alloc) called; s=28
  5. void* operator new[](size_t s, void* object) throw() called; s=28 strlen(object)=33
  6. base(), base constructed sizeof(*this)=8; mIndicate = 1
  7. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  8. base(), base constructed sizeof(*this)=8; mIndicate = 2
  9. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  10. ~superClass(), superClass deconstructed; mIndicate = 2
  11. virtual ~base(), base deconstructed; mIndicate = 2
  12. ~superClass(), superClass deconstructed; mIndicate = 1
  13. virtual ~base(), base deconstructed; mIndicate = 1
  14. void operator delete[] (void* ptr) throw () called; strlen(p)=1
  示例在构造函数第二次运行抛出异常时,即打开宏NEW_FAIL_OPERATOR时的对应输出结果:

点击(此处)折叠或打开

  1. input %%u for input number:
  2. input = 10
  3. paBase = (superClass *) operator new[](2 * superClassSize + 4); sizeof(superClass) = 12
  4. void* operator new[](size_t count) throw(std::bad_alloc) called; s=28
  5. void* operator new[](size_t s, void* object) throw() called; s=28 strlen(object)=33
  6. base(), base constructed sizeof(*this)=8; mIndicate = 1
  7. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 1
  8. base(), base constructed sizeof(*this)=8; mIndicate = 2
  9. superClass(), superClass constructed sizeof(*this)=12; mIndicate = 2
  10. virtual ~base(), base deconstructed; mIndicate = 2
  11. ~superClass(), superClass deconstructed; mIndicate = 1
  12. virtual ~base(), base deconstructed; mIndicate = 1
  13. void operator delete[] (void* ptr, void* voidptr2) throw() called; strlen(ptr)=1;strlen(voidptr2)=1
  14. exception when input = 10 next sequence
    根据示例(10)结果并对比示例(1),我们看出他们的行为很类似却有不同, 事实上delete [] pArryCon10相当于 (pArryCon1 + 1)->~superClass()和pArryCon1->~superClass()及operator delete[](paBase1); 的功能组合, 但是真正不相等, 因为delete []在编译器行为中,作了更多的处理,如规定了析构函数调用顺序, 特别是delete中~superClass抛出异常程序将终止. 当然, 组合的操作可以进行异常catch操作等等.

     谁是谁非, 剑总在有用的人手上才能发挥其作用, 更甚者手中无剑, 却生剑伤.  new/delete 与new[]/delete[]还有更多组合与故事,复杂又艰涩, 我们一直在new/delete路上, 直指前方...

阅读(3235) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~