使用线程的c ++内存泄漏

时间:2014-11-18 12:24:03

标签: multithreading c++11 memory-leaks new-operator delete-operator

我有这段代码的内存泄漏,我不明白为什么。

每个线程都调用exec函数。函数exec只是创建一个std :: vector而不是删除它。此向量的长度等于线程数,并且仅创建和删除一次。

您可以假设此代码是线程安全的,因为只有在创建后才删除该向量。

class Foo{
  public:
  Foo(const std::size_t& numThreads):size_(numThreads){}
  inline void alloc(){std::call_once(bufferflag_,&Foo::alloc_,this);}
  inline void free(){std::call_once(bufferflag_,&Foo::free_,this);}

  private:
  const std::size_t size_;
  std::vector<double>* bufferptr_;
  std::once_flag bufferflag_;

  inline void alloc_(){bufferptr_ = new std::vector<double>(size_);}
  inline void free_(){delete [] bufferptr_;}
};

void exec(Foo& comm){
  comm.alloc();
  // sync the threads here with some barrier
  comm.free();
}

void main(){
  Foo comm(10);
  std::vector<std::thread> t(10);
  for(std::size_t tid=0;tid!=10;++tid) t[tid]=std::thread(exec,std::ref(comm));
  for(std::size_t tid=0;tid!=10;++tid) t[tid].join();
}

HEAP SUMMARY:

在退出时使用:2个块中的104个字节

总堆使用量:23个分配,21个释放,3,704个字节分配

1个块中的104(24个直接,80个间接)字节肯定在2的丢失记录2中丢失

泄漏概要:

绝对丢失:1个块中的24个字节

间接丢失:1个块中的80个字节

可能丢失:0个块中的0个字节

仍然可以访问:0个块中的0个字节

抑制:0个块中的0个字节

更新

如果不使用call_once而只是调用new并从同一个线程中删除,则没有内存泄漏。

1 个答案:

答案 0 :(得分:0)

看看这个修改后的代码:

class Foo
{
public:
    Foo(const std::size_t& numThreads) :size_(numThreads) {}
    inline void alloc()
    {
        printf("alloc\n");
        std::call_once(alloc_flag, &Foo::alloc_, this);
    }
    inline void foo_free()
    {
        printf("free\n");
        std::call_once(free_flag, &Foo::free_, this); // Changed from bufferflag
    }
private:
    const std::size_t size_;
    std::vector<double>* bufferptr_;
    std::once_flag alloc_flag;
    std::once_flag free_flag;

    inline void alloc_()
    { 
        printf("once_alloc_!\n");
        bufferptr_ = new std::vector<double>(size_);
    }
    inline void free_()
    { 
        printf("once_free_!\n");
        bufferptr_->clear();
        delete bufferptr_; // Not delete[] bufferptr_
        bufferptr_ = NULL;
    }
};

void exec(Foo& comm){
    comm.alloc();
    // Barrier
    comm.foo_free();
}

如果你使用2个不同的once_flag用于alloc和free ,你还可以运行free_()方法。您只使用一个标志这一事实会导致内存泄漏,因为第一个alloc会标记消耗

要检查内存泄漏,我使用_CrtDumpMemoryLeaks();,即使我注释掉线程创建/连接例程,我也会得到一些额外的泄漏,但我认为这个std :: vector thrash。希望这有帮助!