重载 '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.
那么,这段代码怎么会造成无限循环,为什么我不应该用cout
和vector
呢?这是书中的一段代码。我尝试使用 vector
、cout
(在 new
运算符内)、push_back
,但无法复制这种情况。那么,这到底什么时候会发生?
void* operator new (size_t size){
if(size > 1000) page_counter++;
return malloc(size);
}
只需告诉 std::vector
在 operator 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";
}
请注意 a) 仅构造一个 std::vector
是不够的,因为那可能无法分配。 std::vector
通常只在您以某种方式告诉它时才分配。当您尝试向其中添加内容时,它会扩展,或者您可以用 reserve
说“至少要这么大”。 b) 你必须从某个地方调用 operator new
来触发循环(这里它在 main
中的 new
内)。
我正在读一本名为
“使用 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.
那么,这段代码怎么会造成无限循环,为什么我不应该用cout
和vector
呢?这是书中的一段代码。我尝试使用 vector
、cout
(在 new
运算符内)、push_back
,但无法复制这种情况。那么,这到底什么时候会发生?
void* operator new (size_t size){
if(size > 1000) page_counter++;
return malloc(size);
}
只需告诉 std::vector
在 operator 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";
}
请注意 a) 仅构造一个 std::vector
是不够的,因为那可能无法分配。 std::vector
通常只在您以某种方式告诉它时才分配。当您尝试向其中添加内容时,它会扩展,或者您可以用 reserve
说“至少要这么大”。 b) 你必须从某个地方调用 operator new
来触发循环(这里它在 main
中的 new
内)。