【发布时间】:2021-05-11 10:14:24
【问题描述】:
最近我遇到了一些内存线程相关的问题。 下面的代码创建 5 个线程,每个线程 push_back 到向量 500'000'000 int 值。 在带有 push_back 的循环结束后,程序仍然使用 ~375M 的虚拟内存,这是我的问题,为什么进程仍然使用这么多内存?
我正在使用 g++ (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0
#include <chrono>
#include <iostream>
#include <thread>
#include <vector>
using namespace std;
void joinAll(vector<thread>& arg)
{
for(auto& item : arg) item.join();
}
int main()
{
vector<thread> threads;
for(int i=0; i<5; ++i)
{
threads.emplace_back([](){
{ // block
vector<int> data;
for(int idx=0; idx<500'000'000; ++idx)
{
data.push_back(idx);
}
} // end of block
cout<<"loop is over\n";
std::this_thread::sleep_for(chrono::seconds(5));
});
}
cout<<"wait in main\n";
std::this_thread::sleep_for(std::chrono::seconds(5));
joinAll(threads);
}
图片呈现htop输出
【问题讨论】:
-
您永远不会检查任何内存不足/资源处理异常。线程和继续执行中未捕获的异常可能会导致整体未定义行为。让您的操作系统停滞不前的大量机会。
-
为了记录,这个例子创建了 1B 个元素的向量,而不是 500M。它最初定义了一个包含 500M 元素的向量,然后再添加 500M。
-
虚拟内存在不再使用时通常不会返回给操作系统。就操作系统所知,该过程即将创建另一个巨大的向量——来回传输内存毫无意义。当进程终止时,或者当另一个进程请求虚拟内存并且操作系统没有任何闲置时,操作系统将回收该内存。仅在内存压力下回收未使用的内存会更有效 - 大多数时候,有很多事情要做。
-
编译您的 C++ 代码,将 GCC 调用为
g++ -Wall -Wextra -O2 -g,然后使用 strace(1) 和 gdb(1) 了解行为和您的可执行文件完成的 syscalls(2)
标签: c++ linux multithreading memory