c++ - bad_alloc 在 Linux 中的作用域和用途是什么?
问题描述
很长一段时间以来,我认为 C++ (STL)bad_alloc
在没有可用内存时会抛出 a 。
但是,根据我听说过的一些关于 Linux 的常识(例如“Linux 在你使用它之前不会真正保留内存”),我决定测试这对bad_alloc
. 事实证明,肯定有某些用途bad_alloc
不会被抛出,因为实际错误发生在allocator
完成其工作之后。
在这个例子中,在第一个循环中,我分配的内存(1TB)明显比我在 Linux Fedora30 系统中的内存要多。
这个循环结束并且下面的循环运行直到我初始化(构造)大约 100GB(= 我的系统中的总 RAM +交换)。
#include<iostream>
#include<memory>
#include<cassert>
#include<vector>
using T = char;
int main(){
std::size_t block_size = 1000000000; // ~1GB
std::size_t n_blocks = 1000; // number of blocks
std::allocator<T> A;
std::vector<T*> ps(n_block);
for(int i = 0; i != n_block; ++i){
cout << "allocating block " << i << std::endl;
ps[i] = A.allocate(block_size); // ps[i] = (char*)malloc(1000000000);
assert(ps[i]);
}
for(int i = 0; i != n_block; ++i){
cout << "constructing block " << i << std::endl;
for(long j = 0; j != block_size; ++j){
A.construct(ps[i] + j, 'z'); // ps[i][j] = 'z'; // hard error "Killed" HERE
}
}
//////////////////////////////// interesting part ends here
for(int i = 0; i != n_block; ++i){
for(long j = 0; j != block_size; ++j){
assert(ps[i][j] == 'z');
A.destroy(ps[i]);
}
A.deallocate(ps[i], block_size);
}
}
我了解操作系统中存在一些特性,并且在许多与系统相关的操作中存在未定义的行为。
我的问题是,我是否以正确的方式使用 C++?在恢复预期行为方面是否需要对这种行为做些什么bad_alloc
?
即使没有,有没有办法提前检测出某些内存不能被触动?检查null
似乎没有涵盖这种情况(同样,在 Linux 中。)
当我在构建这个示例时,我认为,也许,construct
(即其中的位置new
)在检测到原始指针位置的可疑之处时会以某种方式抛出或给出一些错误,但这并没有发生:Linux 只是“杀死”了程序。
这是这个程序在 Fedora30 中的输出,带有 32GB + 64GB 交换:
1
2
3
...
997
998
999
*0
*1
*2
*3
...
*86
*87
*88
*89
*90
Killed
(Linux 输出“Killed”并退出程序)。
注意:我知道程序抛出bad_alloc
. 我正在特别询问像这样的用途,以及在这种情况下是否有办法恢复。
例如,我知道如果我这样做A.allocate("1TB")
会立即抛出一个bad_alloc
。如果我交错分配小块的构造,这也会优雅地发生:
for(int i = 0; i != n_block; ++i){
ps[i] = A.allocate(block_size); //eventually throws, but HERE
for(long j = 0; j != block_size; ++j){
A.construct(ps[i] + j, 'z');
}
}