boost线程池上的内存泄漏

时间:2014-11-03 15:19:43

标签: c++ multithreading boost memory-leaks

我实现了一个线程池,如本讨论中所述Boost group_threads Maximal number of parallel thread

一次更改我有一个等待所有线程完成的函数:

class thread_pool
{
  private:
      mutex mx;
      condition_variable cv;

      typedef function<void()> job_t;
      std::deque<job_t> _queue;

      thread_group pool;

      boost::atomic_bool shutdown;
      static void worker_thread(thread_pool& q)
      {
          while (optional<job_t> job = q.dequeue())
              (*job)();
      }

  public:
      thread_pool() : shutdown(false) {
          //LOG_INFO_MESSAGE << "Number of possible Threads: " << boost::thread::hardware_concurrency() << std::endl;
          for (unsigned i = 0; i < boost::thread::hardware_concurrency(); ++i){
              pool.create_thread(bind(worker_thread, ref(*this)));
          }
      }

      void enqueue(job_t job)
      {

          lock_guard<mutex> lk(mx);
          _queue.push_back(job);

          cv.notify_one();
      }

      optional<job_t> dequeue()
      {
          unique_lock<mutex> lk(mx);
          namespace phx = boost::phoenix;

          cv.wait(lk, phx::ref(shutdown) || !phx::empty(phx::ref(_queue)));

          if (_queue.empty())
              return none;

          job_t job = _queue.front();
          _queue.pop_front();
          return job;
      }

      void WaitTillAllJobsAreDone(){
          shutdown = true;
          {
              lock_guard<mutex> lk(mx);
              cv.notify_all();
          }

          pool.join_all();
      }


      ~thread_pool()
      {
          shutdown = true;
          {
              lock_guard<mutex> lk(mx);
              cv.notify_all();
          }

          pool.join_all();
       }
}; 

我的用法:

class Foo{
public: 
  Foo(std::vector<boost::shared_ptr<Class B> > data):m_data(data),m_maxDepth(5)
{

}
void initializateThreads(){
  thread_pool threadPool;
  std::vector<std::vector<double> > result(m_data.size());
  std::vector<std::vector<double> >::iterator it;=result.begin();
  for(auto d:m_data){
    threadPool.enqueue(boost::bind(&Foo::Work,this,d,boost::ref(*it))):
      ++it;
  }
  threadPool.WaitTillAllJobsAreDone();
  //do something with results;
} 
  void Work(boost::shared_ptr<Class B> ptr,std::vector<double>& resultThread,int currentDepth){
    if(currentDepth>m_maxDepth) return;
    //do some calculation with ptr and add it to resultThread
    resultThread.push_back((double) some result of B);


    Work(ptr,resultThread,(currentDepth+1));
  }
}

当我使用我的线程池时,我的程序在本节后使用了大量内存,并且永远不会释放它。没有线程池我没有相同功能的问题。线程池中有错误吗?我必须释放创建的线程吗?

---------编辑--------------

int main()
{
  {
    std::vector<Class B> data; //filled
    Foo foo(data);
    foo.LoadSomedata();
    foo.initializateThreads();
  } //< all memory should be freed or ?
  while(1){}//< let process alive but memory in ressource manager should be very small or?
}

我写了这个测试程序。 Valgrind还表示没有内存泄漏。当我的程序在while循环中时,我的进程的内存应该非常小或者?但是在系统监视器上,它有3GB用于此过程。我有心理错误吗?

VAlGrind输出:

 ==24210== HEAP SUMMARY:
 ==24210==     in use at exit: 0 bytes in 0 blocks
 ==24210==   total heap usage: 2,055,546 allocs, 2,055,546 frees, 220,359,375 bytes allocated
 ==24210== 
 ==24210== All heap blocks were freed -- no leaks are possible
 ==24210== 
 ==24210== For counts of detected and suppressed errors, rerun with: -v
 ==24210== Use --track-origins=yes to see where uninitialised values come from
 ==24210== ERROR SUMMARY: 8964228 errors from 69 contexts (suppressed: 2 from 2)

我有一些已知的未初始化指针是错误。

1 个答案:

答案 0 :(得分:0)

好吧,泄漏不在您展示的代码中。

查看 Live On Coliru

Valgrind说:All heap blocks were freed -- no leaks are possible

==14398== Memcheck, a memory error detector
==14398== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==14398== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==14398== Command: ./test
==14398== 
....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................==14398== 
==14398== HEAP SUMMARY:
==14398==     in use at exit: 0 bytes in 0 blocks
==14398==   total heap usage: 5,093 allocs, 5,093 frees, 772,512 bytes allocated
==14398== 
==14398== All heap blocks were freed -- no leaks are possible
==14398== 
==14398== For counts of detected and suppressed errors, rerun with: -v
==14398== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

可能是罪魁祸首:

只是做好准备,这样你就可以得到想法:

  • ClassB(或其他相关方)可能违反RuleOfThree。 DEMO 这里的结果是ClassB实施得恰到好处:

    struct ClassB {
        ClassB() : stuff(new int[256]) { }
        int* stuff; // could be other resources, such as threads, filehandles etc.
    };
    

    你可以在valgrind下看到泄漏:

    ==14458== LEAK SUMMARY:
    ==14458==    definitely lost: 510,976 bytes in 499 blocks
    ==14458==    indirectly lost: 0 bytes in 0 blocks
    ==14458==      possibly lost: 1,024 bytes in 1 blocks
    
  • initializateThreads [原文如此]的调用之间,您可能会持有数据向量。

  • 当您希望覆盖时,您可能会附加到相同的数据向量(或输出流缓冲区)

我建议在本地化之前消除泄漏源