重载 'operator new' 怎么会导致死循环呢?

How can overloaded 'operator new' cause infinite loops?

我正在读一本名为 “使用 C++ 进行系统编程实践”。它在第 320 页上说重载 new 运算符会导致无限循环,因此应该避免。

These overloads affect all allocations, including those used by the C++ library, so care should be taken when leveraging these overloads as infinite cyclic recursions could occur if an allocation is performed inside these functions. For example, data structures such as std::vector and std::list, or debugging functions such as std::cout and std::cerr cannot be used as these facilities use the new() and delete() operators to allocate memory.

那么,这段代码怎么会造成无限循环,为什么我不应该用coutvector呢?这是书中的一段代码。我尝试使用 vectorcout(在 new 运算符内)、push_back,但无法复制这种情况。那么,这到底什么时候会发生?

void* operator new (size_t size){
    if(size > 1000) page_counter++;
    return malloc(size);
}

只需告诉 std::vectoroperator new 中分配一些内存就可以了:

void *operator new(std::size_t size) {
    // std::vector<int>::reserve calls std::allocator<int>::allocate calls (this) operator new calls ...
    std::vector<int>().reserve(999);
    return std::malloc(size);
}

int main() {
    int *p = new int(42);
    // OFC, this is undefined behavior, so we *could* reach this, but... we don't, which means it definitely is UB
    std::cout << "Shouldn't reach this!\n";
}

Godbolt shows it crashing

请注意 a) 仅构造一个 std::vector 是不够的,因为那可能无法分配。 std::vector 通常只在您以某种方式告诉它时才分配。当您尝试向其中添加内容时,它会扩展,或者您可以用 reserve 说“至少要这么大”。 b) 你必须从某个地方调用 operator new 来触发循环(这里它在 main 中的 new 内)。