运算符new失败时的构造函数调用

Constructor call when operator new failed

本文关键字:函数调用 new 失败 运算符      更新时间:2023-10-16

我正在尝试实现一种技术来测试失败的运算符new,如中所述http://www.codeproject.com/Articles/6108/Simulating-Memory-Allocation-Failure-for-Unit-Test.

这是一个正在测试的示例代码:

VArray* arr = new VArray(1U, 3U, true);

我可以让new返回NULL,而不是分配内存。在这种情况下,程序应该继续到下一行(应该测试arr == NULL),这正是它在MSVC中所做的。

然而,在GCC中失败的new之后,仍然调用VArray的构造函数。由于thisNULL,因此在对属性的第一次赋值时会产生SIGSEGV。根据C++03标准,这似乎是一种错误的行为:https://stackoverflow.com/a/11514528/711006

下面是我对运算符newdelete的实现。

unsigned int OperatorPlainNewFailsAfter = UINT_MAX;
void* operator new(const size_t _size) throw()
{
  void* result;
  if(OperatorPlainNewFailsAfter == 0U)
  {
    result = NULL;
  }
  else
  {
    result = malloc(_size);
    OperatorPlainNewFailsAfter--;
  }
  return result;
}
void operator delete(void* _memory) throw()
{
  free(_memory);
}

我想念什么?

C++标准要求分配函数(例如基本operator new)在失败时抛出std::bad_alloc异常,从而失败。不允许返回null指针。当您返回一个null指针时,您有未定义的行为,是的,一个可能的结果是调用了构造函数。

如果被调用的operator new被声明为throw(),那么编译器不检查空指针是错误的。但宣布一个非配售的新throw()是违法的,所以编译器检查它没有意义;如果有什么不同的话应该在看到声明时进行投诉,因为隐式地声明非放置CCD_ 16。

如果你想测试new是否失败(这是个好主意),CCD_ 18函数不应该返回空指针,但应该抛出CCD_ 19。否则,你就不会测试同样的东西。在您站点的页面上,测试代码而是使用新的放置。该代码仍然是非法的,因为他的operator new可能返回空指针已经声明了函数throw(),但这很容易固定的(或者没有。他叫::operator new,而不是malloc,用于实际分配,并且此函数可能投他还调用CCD_ 24函数进行分配,但使用了CCD_ 25算子去自由;如果你打电话::operator new分配,您应该调用::operator delete释放。)当然,即使修复了,也不会测试任何有用的东西,因为你需要知道的是程序对std::bad_alloc的反应是正确的,而不是对它永远看不到的空指针做出正确反应。