【发布时间】:2015-12-17 03:41:01
【问题描述】:
我正在尝试从 Stroustrup 的 C++PL4 书中做一个练习。任务是:
使用
new分配如此多的内存,导致bad_alloc被抛出。报告方式 分配了多少内存以及花费了多少时间。这样做两次: 一次不写入分配的内存,一次写入每个 元素。
以下代码不会引发std::bad_alloc 异常。执行程序后,我在终端中收到消息“Killed”。
还有。以下代码在约 4 秒内退出。但是当我取消注释内存使用消息时
// ++i;
// std::cout << "Allocated " << i*80 << " MB so far\n";
程序将运行几分钟。一段时间后,它会打印出已分配 TB 的内存,但我没有看到 System Monitor 应用程序有太大变化。这是为什么呢?
我使用 Linux 和 System Monitor 应用来查看使用情况。
#include <iostream>
#include <vector>
#include <chrono>
void f()
{
std::vector<int*> vpi {};
int i {};
try{
for(;;){
int* pi = new int[10000];
vpi.push_back(pi);
// ++i;
// std::cout << "Allocated " << i*80 << " MB so far\n";
}
}
catch(std::bad_alloc){
std::cerr << "Memory exhausted\n";
}
}
int main() {
auto t0 = std::chrono::high_resolution_clock::now();
f();
auto t1 = std::chrono::high_resolution_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(t0-t1).count() << " ms\n";
}
【问题讨论】:
-
与简单的内存分配相比,输出将花费 很多 的时间。如果运行 2 分钟,输出可能是 1:56,分配仍然是 4 秒。
-
在现代残酷的世界中,调用
new(以及malloc甚至brk())并不一定会分配内存。它只是(通过层链)向操作系统发送一个请求,并且操作系统分配一个 virtual 内存区域(四舍五入到页面)。所以只有访问给定的页面会执行内存分配。此外,现代操作系统允许“过度使用”,即从操作系统可以分配的不同应用程序分配更多内存,即使使用交换也是如此。这样做是因为很少有所有应用程序同时需要所有分配的内存,并且可以依次满足它们的实际需求。 -
在最坏的情况下,当应用程序确实访问它们的内存时,一个名为 OOM Killer 的特殊系统服务会出现并杀死应用程序(几乎是随机的:))。所以依赖
bad_alloc确实是个坏主意,它可能会提高,也可能不会,这取决于当前的操作系统设置和应用程序执行时的其他应用程序行为。 -
为了增加实际分配虚拟页面的机会,您可以访问刚刚分配的元素,但这也不是逐字保证,只是增加了可能性
标签: c++ exception out-of-memory bad-alloc