很长时间以来,尽管没有可用内存,但C ++(STL)会抛出bad_alloc
。
但是,在我听说过一些有关Linux的常识的指导下(例如“ Linux不会真正保留内存,除非您使用它”),我决定测试该行为对{{1} }。
事实证明,肯定有某些用途不会抛出bad_alloc
,因为实际的错误发生在bad_alloc
完成工作之后。
在此示例中,在第一个循环中,我明显分配了更多的内存(1TB) 比我的Linux Fedora30系统要强。
此循环结束,直到下面的循环运行,直到大约初始化(构造)大约100GB(=系统中的总RAM +交换)。
allocator
我知道操作系统中有一些特质,并且在许多与系统相关的操作中都存在未定义的行为。
我的问题是,我是否以正确的方式使用C ++?在恢复预期的#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);
}
}
行为方面,该行为有待解决吗?
即使没有,是否有办法检测到某些内存无法被预先触摸?检查bad_alloc
似乎无法解决这种情况(同样在Linux中)。
虽然我在构建此示例,但也许,null
(即其中的放置位置construct
)在检测到一些可疑的东西时会以某种方式抛出或给出一些错误关于原始指针的位置,但那没有发生:Linux只是“杀死”了程序。
这是Fedora30中此程序的输出,具有32GB + 64GB交换空间:
new
(Linux输出“杀死”并退出程序)。
注意:我知道程序会引发1
2
3
...
997
998
999
*0
*1
*2
*3
...
*86
*87
*88
*89
*90
Killed
的其他用途(例如,块大小,不同的顺序-交错的-分配和构造等)。我专门询问这种用途,是否有办法在这种情况下进行恢复。
例如,我知道如果我执行bad_alloc
,则会立即抛出A.allocate("1TB")
。
如果我对小块的结构分配进行交错,也会很好地发生这种情况:
bad_alloc