【问题标题】:Constructor call when operator new failed新运算符失败时的构造函数调用
【发布时间】:2023-03-29 05:28:01
【问题描述】:

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

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

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

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

但是,VArray 的构造函数在 GCC 中失败的new 之后仍然被调用。由于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);
}

我错过了什么?

【问题讨论】:

  • 替换 operator new 必须在失败时抛出 std::bad_alloc。返回NULL 是违反合同的。 “必需的行为:返回一个指向适当对齐存储 (3.7.4) 的非空指针,否则抛出 bad_alloc 异常。此要求绑定到此函数的替换版本。”

标签: c++ gcc c++03


【解决方案1】:

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

【讨论】:

  • 感谢您的提示,但我的初衷是替换new (std::nothrow),我同意我已经完成了一半。所以你帮我正确完成了。
【解决方案2】:

如果被调用的operator new 被声明为throw(),那么 编译器不检查空指针是错误的。 但是声明一个非放置newthrow()是违法的,所以 编译器检查它没有意义;如果有的话,它 当它看到声明时应该抱怨,因为 非放置operator new 被隐式声明。

如果你想测试失败的new(这是个好主意), 您的 operator new 函数不应返回空指针, 但应该抛出std::bad_alloc。否则,你不是 测试同样的事情。在您站点的页面上,测试代码 改用新的展示位置。代码仍然是非法的, 因为他的operator new 可能会返回一个空指针而不 已经声明了函数throw(),但这很容易 固定的。 (或者不是。他打电话给::operator new,而不是 malloc,实际分配,这个函数可以 扔。他还调用::operator new函数进行分配, 但使用了::delete 运算符de free;如果你打电话 ::operator new 分配,你应该调用::operator delete 释放。)当然,即使固定,它不测试 任何有用的东西,因为你需要知道的是你的 程序正确响应std::bad_alloc,而不是它 对它永远不会看到的空指针做出正确反应。

【讨论】:

  • 感谢您对原始示例的彻底检查。是的,我修改了它,因为放置 new 不是我想要测试的东西。由于我要替换“基本”全局 new,我不能调用 ::operator new,因为它已被替换!这就是mallocfree 的原因。
猜你喜欢
  • 2017-04-09
  • 1970-01-01
  • 2017-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-03
  • 1970-01-01
  • 2011-05-21
相关资源
最近更新 更多