提升线程池内存泄漏

Memory leak on boost thread pool

本文关键字:内存 泄漏 线程      更新时间:2023-10-16

我实现了本讨论中描述的线程池Boost group_threads并行线程的最大数量

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

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)

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

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

请参阅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(或其他相关方)可能违反RuleOfThreeDEMO以下是适当破坏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[sic]之间,您可能会保留数据向量。

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

我建议消除泄漏源,直到您将其本地化