函数不会抛出 bad_alloc 异常
function doesn't throw bad_alloc exception
我正在尝试从 Stroustrup 的 C++PL4 书中做一个练习。任务是:
Allocate so much memory using new
that bad_alloc
is thrown. Report how
much memory was allocated and how much time it took. Do this twice:
once not writing to the allocated memory and once writing to each
element.
以下代码不会引发 std::bad_alloc
异常。执行程序后,我在终端中收到消息 "Killed"。
还有。以下代码在 ~4 秒后退出。但是当我取消注释内存使用消息时
// ++i;
// std::cout << "Allocated " << i*80 << " MB so far\n";
程序将 运行 持续几分钟。一段时间后,它打印出已经分配了 TB 的内存,但我没有看到系统监视器应用程序有太大变化。这是为什么?
我使用 Linux 和系统监视器应用程序来查看使用情况。
#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";
}
在现代残酷的世界中,调用 new
(以及 malloc()
甚至 brk()
)不一定会分配内存。它只是(通过层链)向 OS 发送请求,然后 OS 分配 虚拟 内存区域(四舍五入为系统内存页面)。因此只有随后 访问 给定内存才能执行实际分配。
此外,现代 OSes 允许记忆 "overcommit"。有时(取决于 OS 及其设置)应用程序可能需要完全更多的内存,甚至在理论上 OS 可以分配,包括它的所有交换区域等,所有 w/o 任何可见的问题。例如看at this page。
这样做是因为在现实生活中,所有应用程序实际上都在同时使用所有分配的内存的情况是非常不可能的。更常见的是,99.99..% 的时间,应用程序只使用部分内存并按顺序执行,因此 OS 有机会无缝地满足他们的请求。
为了增加实际导致内存分配错误的机会,您可以访问刚刚分配的元素,但我不会将其称为逐字保证,只是"about increasing possibilities".
在最坏的情况下,当这样的 OS 实际上发现它无法分配足够的(虚拟)内存,因为太多的应用程序同时请求访问它们无缝分配的数据时,OS 内存管理器启动一个名为 "OOM killer" 的特殊程序,该程序简单地试探性地(= 随机 :))杀死选定的应用程序。
所以现在依赖 bad_alloc
是个坏主意。有时您可以可靠地接收它(例如,当人为地使用 ulimit/setrlimit 限制您的应用程序时),但通常您的应用程序将 运行 在无法保证任何事情的环境中。只是不要成为记忆猪并为休息祈祷:)
我正在尝试从 Stroustrup 的 C++PL4 书中做一个练习。任务是:
Allocate so much memory using
new
thatbad_alloc
is thrown. Report how much memory was allocated and how much time it took. Do this twice: once not writing to the allocated memory and once writing to each element.
以下代码不会引发 std::bad_alloc
异常。执行程序后,我在终端中收到消息 "Killed"。
还有。以下代码在 ~4 秒后退出。但是当我取消注释内存使用消息时
// ++i;
// std::cout << "Allocated " << i*80 << " MB so far\n";
程序将 运行 持续几分钟。一段时间后,它打印出已经分配了 TB 的内存,但我没有看到系统监视器应用程序有太大变化。这是为什么?
我使用 Linux 和系统监视器应用程序来查看使用情况。
#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";
}
在现代残酷的世界中,调用 new
(以及 malloc()
甚至 brk()
)不一定会分配内存。它只是(通过层链)向 OS 发送请求,然后 OS 分配 虚拟 内存区域(四舍五入为系统内存页面)。因此只有随后 访问 给定内存才能执行实际分配。
此外,现代 OSes 允许记忆 "overcommit"。有时(取决于 OS 及其设置)应用程序可能需要完全更多的内存,甚至在理论上 OS 可以分配,包括它的所有交换区域等,所有 w/o 任何可见的问题。例如看at this page。
这样做是因为在现实生活中,所有应用程序实际上都在同时使用所有分配的内存的情况是非常不可能的。更常见的是,99.99..% 的时间,应用程序只使用部分内存并按顺序执行,因此 OS 有机会无缝地满足他们的请求。
为了增加实际导致内存分配错误的机会,您可以访问刚刚分配的元素,但我不会将其称为逐字保证,只是"about increasing possibilities".
在最坏的情况下,当这样的 OS 实际上发现它无法分配足够的(虚拟)内存,因为太多的应用程序同时请求访问它们无缝分配的数据时,OS 内存管理器启动一个名为 "OOM killer" 的特殊程序,该程序简单地试探性地(= 随机 :))杀死选定的应用程序。
所以现在依赖 bad_alloc
是个坏主意。有时您可以可靠地接收它(例如,当人为地使用 ulimit/setrlimit 限制您的应用程序时),但通常您的应用程序将 运行 在无法保证任何事情的环境中。只是不要成为记忆猪并为休息祈祷:)