我调试了一个奇怪的内存问题:当一个多线程算法在一个循环中运行时,它的内存消耗随着每次迭代而增加,尽管GooglePerformanceTools的堆检查器说没有泄漏。最后,我制作了一个单独的最小程序来重现该bug。似乎线程是问题所在:
#include <stdio.h>
#include <iostream>
#include <vector>
#include "tinythread.h"
using namespace std;
int a(0);
void doNothingAtAll(void*)
{
++a;
}
void startAndJoin100()
{
vector<tthread::thread*> vThreads;
for(int i=0;i<100;++i)
{
vThreads.push_back(new tthread::thread(doNothingAtAll,NULL));
}
while(!vThreads.empty())
{
tthread::thread* pThread(vThreads.back());
pThread->join();
delete pThread;
vThreads.pop_back();
}
}
int main()
{
for(int i=0;i<10;++i)
{
cout<<"calling startAndJoin100()"<<endl;
startAndJoin100();
cout<<"all threads joined"<<endl;
cin.get();
}
return 0;
}
main()调用10次startAndJoin100()。它在每次迭代后等待一次键击,以便可以占用内存消耗(在Ubuntu 17.10,64位下):
VIRT
2.1 GB
4 GB
5.9 GB
7.8 GB
9.6 GB
11.5 GB
13.4 GB
15.3 GB
17.2 GB
19.0 GB
注意:不能使用C ++ 11,程序必须在Linux和Windows上编译,因此使用tinythread。使用Makefile的最小测试代码: geom.at/_downloads/testTinyThread.zip
答案 0 :(得分:1)
我回答我自己的问题,这对以后的某人可能有用:
结论:
1)我真的想保留TinyThread,因为C ++ 11不可用(必须支持VS2008和旧Linux系统)并且不应链接其他库(TinyThread只包含* .h和* .cpp文件,而我知道Boost和其他解决方案需要链接DLL)。
2)Valgrind和GooglePerformanceTools的堆检查器不会报告内存泄漏,我已经查看了代码 - 虽然虚拟内存消耗在上面发布的最小示例中大幅增加,但似乎是正确的。似乎系统没有重新使用以前分配的内存页面,我没有找到这种行为的解释。因此,我不会责怪TinyThread ++,但是当直接使用pthread时它会起作用。
3)解决方法:有一个名为TinyCThread的C替代方案:https://tinycthread.github.io/也适用于C ++,它不会导致TinyThread ++观察到的问题。