gpt4 book ai didi

c++ - 多线程程序中意外的内存泄漏

转载 作者:行者123 更新时间:2023-12-01 15:10:59 30 4
gpt4 key购买 nike

我正在使用大量线程的程序上工作,每个线程在堆中分配几兆字节的内存。当这些线程结束时,程序将保留大部分RAM。

这是一个代码示例,它在500个线程中分配和释放1 MB内存,这显示了此问题:

#include <future>
#include <iostream>
#include <vector>

// filling a 1 MB array with 0
void task() {
const size_t S = 1000000;
int * tab = new int[S];
std::fill(tab, tab + S, 0);
delete[] tab;
}

int main() {
std::vector<std::future<void>> threads;
const size_t N = 500;

std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "Starting threads" << std::endl;

for (size_t i = 0 ; i < N ; ++i) {
threads.push_back(std::async(std::launch::async, [=]() { return task(); }));
}

for (size_t i = 0 ; i < N ; ++i) {
threads[i].get();
}

std::cout << "Threads ended" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(25));

return 0;
}

在我的计算机上,此代码仅由 g++ -o exe main.cpp -lpthread构建,在消息“正在启动线程”之前使用1976 kB,在消息“线程结束”之后使用419 MB。这些值仅是示例:当我多次运行程序时,我可以得到不同的值。

我已经尝试过valgrind/memcheck,但是它没有检测到任何泄漏。

我注意到,用互斥锁锁定“std::fill”操作似乎可以解决此问题(或在很大程度上减少它),但是我不认为这是竞争条件问题,因为这里没有共享内存。我想互斥锁只是在线程之间创建一个执行顺序,从而避免(或减少)内存泄漏的情况。

我正在使用带有GCC 7.4.0的Ubuntu 18.04。

谢谢您的帮助。

Aurélien

最佳答案

整个谜团隐藏在负责管理内存的标准库中。多线程仅在每个踏步需要大量内存的情况下才对内存消耗产生影响(出于某些原因,大多数初学者不记得这一点)。

当您调用delete(或C语言中的free)时,并不意味着内存会返回系统。这仅意味着标准库会将这部分内存标记为不再需要。

现在,由于从系统请求内存或向系统释放内存非常昂贵,并且可以分块完成(页面大小为8-32 kB,具体取决于硬件),因此标准库会尝试对此进行优化,并且不会将所有内存返回给系统立即地。假定程序可能很快会再次需要此内存。

因此,进程消耗的内存不是指示内存泄漏的好数字。仅当进程运行较长时间,保持相同状态并连续获取内存时,您才可以怀疑程序会泄漏内存。
在所有其他情况下,您都应该使用valgrind之类的工具(我建议使用地址清理器)。

还有其他优化会影响您所看到的内容。生成线程的成本很高,因此当线程完成其工作时,不会完全销毁它。它保存在“线程池”中,以备将来重用。

关于c++ - 多线程程序中意外的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60109770/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com