C++ 函数不';t抛出错误的\u alloc异常

C++ 函数不';t抛出错误的\u alloc异常,c++,exception,out-of-memory,bad-alloc,C++,Exception,Out Of Memory,Bad Alloc,我正试图从Stroustrup的C++PL4书中做一个练习。任务是: 使用new分配大量内存,导致抛出bad\u alloc。报告方式 分配了多少内存以及花费了多少时间。这样做两次: 一次不写入分配的内存,一次写入每个内存 元素 以下代码不会引发std::bad_alloc异常。在我执行程序之后,我在终端中得到消息“Killed” 还有。以下代码将在约4秒后退出。但当我取消注释内存使用消息时 // ++i; // std::cout << "Allocated " <<

我正试图从Stroustrup的C++PL4书中做一个练习。任务是:

使用
new
分配大量内存,导致抛出
bad\u alloc
。报告方式 分配了多少内存以及花费了多少时间。这样做两次: 一次不写入分配的内存,一次写入每个内存 元素

以下代码不会引发
std::bad_alloc
异常。在我执行程序之后,我在终端中得到消息“Killed”

还有。以下代码将在约4秒后退出。但当我取消注释内存使用消息时

// ++i;
// std::cout << "Allocated " << i*80 << " MB so far\n";
//++i;

//std::cout在现代残酷的世界中,调用
new
(以及
malloc()
甚至
brk()
)并不一定分配内存。它只是(通过一系列层)向操作系统发送一个请求,操作系统分配一个虚拟内存区域(四舍五入到系统内存页)。因此,只有对给定内存的后续访问才能执行实际分配

此外,现代操作系统允许内存“过度使用”。有时(取决于操作系统及其设置),应用程序可能需要操作系统甚至理论上可以分配的更多内存,包括其所有交换区等,所有这些都不存在任何可见问题。比如说

之所以这样做,是因为在现实生活中,所有应用程序实际上不可能同时使用所有分配的内存。更常见的情况是,99.99….%的时间,应用程序只使用部分内存,并按顺序执行,因此操作系统有机会无缝地为其请求提供服务

为了增加实际导致内存分配错误的机会,您可以访问刚刚分配的元素,但我不会将其称为逐字保证,只是“关于增加可能性”

在最坏的情况下,当这样一个操作系统发现它无法分配足够的(虚拟)内存,因为有太多的应用程序同时请求访问其分配的数据时,操作系统内存管理器会启动一个名为“OOM killer”的特殊过程,该过程简单地以启发式(=随机:)方式杀死选定的应用程序


因此,如今依赖于坏的分配是个坏主意。有时你可以真正地接收到它(例如,当人为地限制你的应用程序时),但一般来说,你的应用程序将在一个无法保证任何东西的环境中运行。只是不要成为一个内存猪,为剩下的祈祷:)

输出将比简单的内存分配花费更多的时间。如果运行2分钟,输出可能是1:56,分配可能是4秒。在现代残酷的世界中,调用
new
(以及
malloc
,甚至
brk()
)并不一定分配内存。它只是(通过一系列层)向操作系统发送一个请求,操作系统分配一个虚拟内存区域(四舍五入到页面)。因此,只有访问给定页面才能执行内存分配。此外,现代操作系统允许“过度使用”,即从不同的应用程序中分配更多的内存,即使使用交换,操作系统也可以分配这些内存。之所以这样做,是因为几乎所有应用程序都不需要一次分配所有的内存,而且可以依次满足它们的实际需要。在最坏的情况下,当应用程序确实访问了它们的内存时,一个名为OOM Killer的特殊系统服务进入场景并杀死应用程序(几乎是随机的:)。因此,依赖于
bad_alloc
是一个坏主意。事实上,它可能会被提出,也可能不会,这取决于当前的操作系统设置和应用程序执行时的其他应用程序行为。为了增加实际分配虚拟页面的机会,您可以访问刚刚分配的元素,但这不是逐字保证,增加可能性也可以查看这篇文章:
#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";
}