线程占用内存

时间:2014-10-09 17:03:06

标签: c++ boost boost-thread

我有正确使用线程的问题(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,它们会被正确清除)

3 个答案:

答案 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我没有资源来调试线程清理中的竞争条件。