我有正确使用线程的问题(boost :: thread)
我希望X线程同时运行相同的功能
while( true )
server.run();
我目前编程的方式是哪种,这是运行功能
void server::run()
{
std::vector<boost::thread*> threads;
for(std::size_t i = 0; i < threadPool; ++i)
{
threads.push_back( new boost::thread( boost::bind(&seed::server::pollEvent,this) ) );
}
for( auto & x : threads )
x->join();
for( auto & x : threads )
x->detach();
for( auto & x : threads )
delete x;
}
但是,这会继续占用越来越多的RAM,从~20MB开始上升到无穷大,我的问题是,对此有什么正确的解决方法?
Minimal example of what I'm actually doing
使用SFML的线程时不会发生此问题。 (CPU使用率略高,但不会占用每个线程的ram,它们会被正确清除)
答案 0 :(得分:6)
for( unsigned int i = threads.size()-1; i > 0; i-- )
delete threads[i];
你永远不会delete threads[0]
。 for循环条件不正确,因为我在循环体内永远不会变为0。此外,您不需要在此处进行反向迭代,因为您没有删除实际元素。因此
for( auto & x : threads )
delete x;
就足够了。
其次,你违反了boost::thread::detach
的先决条件。它说
前提条件: 线程是可连接的。
但你已经加入了他们。线程可能代表连接后的非线程(连接的后置条件):
后置条件:如果*这是指进入时执行的线程,则该执行线程已完成。 *这不再涉及任何执行线程。
由于这个问题,您的应用程序是否会创建疯狂的线程数量,这可能是值得的。我不这么认为,但比抱歉更安全。
-
最小的例子不泄漏。 (提升1.56.0,GCC 4.9.1,Linux)
顺便说一下,提供的最小例子不编译,这里是固定版本:#include <boost/thread.hpp>
#include <vector>
class server
{
public:
server( unsigned short int thrNum )
{
if( thrNum )
threadPool = thrNum;
};
~server()
{
};
void run()
{
std::vector<boost::thread*> threads;
for(std::size_t i = 0; i < threadPool; ++i)
{
threads.push_back( new boost::thread( boost::bind(&server::pollEvent,this) ) );
}
for( auto & x : threads )
x->join();
for( auto & x : threads )
x->detach();
for( auto & x : threads )
delete x;
};
private:
void pollEvent() { return; };
unsigned short int threadPool = 1;
};
int main()
{
server s(4);
while(true)
s.run();
return 1;
}
答案 1 :(得分:0)
答案: 您正在线程对象上调用detach()。这将真正的底层线程(及其堆栈)与boost线程分离,在调用 - &gt; delete()的时候将其取消删除。
如果你有c ++ 11,为什么要使用boost线程呢? std :: thread是可移动的,因此可以在没有new / delete的向量中工作。
上述最小例子的另一次迭代:
#include <thread>
#include <vector>
static const int threadPool = 4;
void noop()
{
}
void run()
{
std::vector<std::thread> threads;
for(std::size_t i = 0; i < threadPool; ++i)
{
threads.push_back( std::thread( noop ) );
}
for( auto & x : threads )
x.join();
}
int main()
{
while(true)
run();
return 1;
}
答案 2 :(得分:0)
我对你的问题没有答案,但我确实有一些我认为有趣但不适合评论的信息。
首先,我能够使用在Win7 x64上运行的MinGW 4.8.1重现您的问题,程序内置为32位x86进程(我不是说x64版本没有重复问题;我没有尝试过x64因为我的MinGW Boost库只是为32位构建的。如果重要,我的Boost库是为静态链接而构建的,我使用了调试版本。
使用MSVC 12(Visual Studio 2013)构建时,问题不重现。
另外,我可以简化将问题重现的程序,以消除detach()
,指针和动态内存分配的所有干扰:
#include <windows.h>
#include <boost/thread.hpp>
void thread_func()
{
// Sleep(1);
return;
}
int main()
{
for (;;) {
boost::thread t1(thread_func);
boost::thread t2(thread_func);
t1.join();
t2.join();
}
}
使内存泄漏消失(或者至少缓慢到看不见的地方)并不需要太多。以下任何一种似乎都适合我:
Sleep(1)
t1.join()
t2
移至
不幸的是,使用gbd我没有资源来调试线程清理中的竞争条件。