4

我有以下声明:

void * operator new (size_t s, PersistentMemory * m) throw()
   {return m->allocatePersistentMemory(s);}

我正在测试启动时的内存耗尽,这会导致m->allocatePersistentMemory(s);返回 0。New 然后使用空指针调用构造函数this

但是,基于 C++ 2003 标准的 3.7.3.1 第 3 段:

分配存储失败的分配函数可以调用当前安装的 new_handler (18.4.2.2),如果有的话。[注意:程序提供的分配函数可以使用 set_new_handler 函数 (18.4.2.3) 获取当前安装的 new_handler 的地址。] 如果使用空异常规范 (15.4) 声明的分配函数 throw() 未能分配存储,它应返回空指针。任何其他分配存储失败的分配函数只能通过抛出类 std::bad_alloc (18.4.2.1) 或从 std::bad_alloc 派生的类的异常来指示失败。

我理解事物的方式是m->allocatePersistentMemory(s)返回 null 应该导致整个operator new() throw()返回 null 而无需调用构造函数。我是否在其他地方遗漏了其他一些可以覆盖这一点的条件?

谢谢!

4

2 回答 2

2

C++03 标准的第 5.3.4 (13) 节说:

[注意:除非使用空 异常规范(15.4)声明分配函数,否则通过抛出bad_alloc异常(条款15、18.4.2.1)throw()表示分配存储失败;否则它返回一个非空指针。如果分配函数声明为空异常规范, ,则返回 null 以指示分配存储失败,否则返回非空指针。] 如果分配函数返回null,则不进行初始化,不调用deallocation函数,new-expression的值为null。throw()

短语“不应进行初始化”意味着不会调用构造函数。

有趣的是——除非我读错了规范——当你的分配函数指定throw()并返回 null 时,“new”本身的调用值是 null。我一直认为这是不可能的(例如,请参阅Will new return NULL in any case? 中的几乎所有答案? )。

于 2012-07-17T00:32:09.503 回答
2

我怀疑你没有打电话给new你认为你在打电话。

这可以按您的预期工作。

void *myalloc (size_t) { return 0; }
void * operator new (size_t s) throw() { return myalloc(s); }
struct Foo {
    std::string s;
    Foo () { std::cout << this << std::endl; }
};
int main () {
    Foo *f = new Foo;
    if (f == 0) std::cout << "f is NULL" << std::endl;
}

在哪里,这失败了。

void *myalloc (size_t) { return 0; }
void * operator new (size_t s) throw() { return myalloc(s); }
struct Foo {
    std::string s;
    Foo () { std::cout << this << std::endl; }
    void * operator new (size_t s) { return myalloc(s); }
};
int main () {
    Foo *f = new Foo;
    if (f == 0) std::cout << "f is NULL" << std::endl;
}
于 2012-07-17T00:43:35.980 回答