tom*_*tom 5 c++ exception out-of-memory bad-alloc
我正在尝试从Stroustrup的C++ PL4书中做一个练习.任务是:
使用分配这么多的内存
new是bad_alloc被抛出.报告分配了多少内存以及花费了多少时间.这样做两次:一次不写入分配的内存,一次写入每个元素.
以下代码不会引发std::bad_alloc异常.执行程序后,我在终端收到消息"Killed".
也.以下代码在~4秒内退出.但是当我取消注释内存使用消息时
// ++i;
// std::cout << "Allocated " << i*80 << " MB so far\n";
Run Code Online (Sandbox Code Playgroud)
程序将运行几分钟.经过一段时间后,它打印出已经分配了数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";
}
Run Code Online (Sandbox Code Playgroud)
在现代残酷的世界中,呼唤new(以及malloc()甚至brk())不一定分配记忆.它只是(通过一系列层)向OS发送请求,并且OS分配虚拟内存区域(四舍五入到系统内存页面).因此,只有后续访问给定内存才能执行实际分配.
此外,现代操作系统允许内存"过度使用".有时(取决于操作系统及其设置)应用程序可以要求操作系统甚至可以在理论上分配更多的内存,包括所有交换区域等,所有内容都没有任何明显的问题.看看这个网页的例子.
这样做是因为在现实生活中所有应用程序实际上在同一时间实际使用所有分配的内存的情况是不太可能的.更常见的是,99.99%的时间,应用程序仅使用部分内存并且经常执行,因此操作系统有机会无缝地提供请求.
为了增加实际导致内存分配错误的可能性,您可以访问刚刚分配的元素,但我再也不会将其称为逐字保修,只是"关于增加可能性".
在最糟糕的情况下,当这样的操作系统实际上发现它无法分配足够的(虚拟)内存,因为太多的应用程序同时请求访问其分离的分配数据时,操作系统内存管理器启动一个称为"OOM杀手"的特殊程序,它只是试探性地杀死(=随机:))选择的应用程序.
如此依赖bad_alloc是一个坏主意.有时您可以实际接收它(例如,当使用ulimit/setrlimit人为地限制您的应用程序时),但通常您的应用程序将在不保证任何内容的环境中运行.只是不要记忆,并为其余的祈祷:)