使用valgrind的C ++中的矢量分配中的内存泄漏

时间:2019-02-21 03:17:45

标签: c++ vector memory-leaks valgrind

我用valgrind检查我用C ++编写的项目。它告诉我在进行向量分配的过程中肯定存在内存泄漏。

valgrind告诉的是

==37533== 514,604 bytes in 124,984 blocks are definitely lost in loss record 369 of 433
==37533==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==37533==    by 0x42BB89: __gnu_cxx::new_allocator<int>::allocate(unsigned long, void const*) (new_allocator.h:104)
==37533==    by 0x42832B: std::allocator_traits<std::allocator<int> >::allocate(std::allocator<int>&, unsigned long) (alloc_traits.h:491)
==37533==    by 0x424565: std::_Vector_base<int, std::allocator<int> >::_M_allocate(unsigned long) (stl_vector.h:170)
==37533==    by 0x48B73F: int* std::vector<int, std::allocator<int> >::_M_allocate_and_copy<__gnu_cxx::__normal_iterator<int const*, std::vector<int, std::allocator<int> > > >(unsigned long, __gnu_cxx::__normal_iterator<int const*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int const*, std::vector<int, std::allocator<int> > >) (stl_vector.h:1224)
==37533==    by 0x48B2BD: std::vector<int, std::allocator<int> >::operator=(std::vector<int, std::allocator<int> > const&) (vector.tcc:195)
==37533==    by 0x603A49: Dict::DATrieT<unsigned short, std::vector<unsigned short, std::allocator<unsigned short> >, std::vector<int, std::allocator<int> > >::buildTrie(std::vector<Dict::DATrieT<unsigned short, std::vector<unsigned short, std::allocator<unsigned short> >, std::vector<int, std::allocator<int> > >::TermCode, std::allocator<Dict::DATrieT<unsigned short, std::vector<unsigned short, std::allocator<unsigned short> >, std::vector<int, std::allocator<int> > >::TermCode> > const&, std::vector<std::vector<Dict::DATrieT<unsigned short, std::vector<unsigned short, std::allocator<unsigned short> >, std::vector<int, std::allocator<int> > >::TrieNode, std::allocator<Dict::DATrieT<unsigned short, std::vector<unsigned short, std::allocator<unsigned short> >, std::vector<int, std::allocator<int> > >::TrieNode> >*, std::allocator<std::vector<Dict::DATrieT<unsigned short, std::vector<unsigned short, std::allocator<unsigned short> >, std::vector<int, std::allocator<int> > >::TrieNode, std::allocator<Dict::DATrieT<unsigned short, std::vector<unsigned short, std::allocator<unsigned short> >, std::vector<int, std::allocator<int> > >::TrieNode> >*> >&) (Datrie.cpp:467)
==37533==    by 0x602758: Dict::DATrieT<unsigned short, std::vector<unsigned short, std::allocator<unsigned short> >, std::vector<int, std::allocator<int> > >::build(std::vector<Dict::DATrieT<unsigned short, std::vector<unsigned short, std::allocator<unsigned short> >, std::vector<int, std::allocator<int> > >::TermCode, std::allocator<Dict::DATrieT<unsigned short, std::vector<unsigned short, std::allocator<unsigned short> >, std::vector<int, std::allocator<int> > >::TermCode> > const&) (Datrie.cpp:178)
==37533==    by 0x602103: Loader::Trie_Loader::InnerLoad(BaseDict_Collection&) (Trie_Loader.cpp:116)
==37533==    by 0x473BA6: deduce::DeduceClassify::Get_Dat_EntityRec() (DeduceClassify.cpp:500) 
==37533==    by 0x470D7A: deduce::DeduceClassify::init(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<Qp_Dict> const&, Analyse::Analysis*, MINISEARCH::Index*, Normalization::Normalizer*) (DeduceClassify.cpp:53)
==37533==    by 0x40E784: queryparser::CQueryParserImpl::Init(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (QueryParserImpl.cpp:120)

代码段是

if ((int) (*itVecIter)->code.size() == nLevel + 1)
{ 
    treeNode.bEnd = true;
    // NOTE: the memory leak happens at following
    treeNode.weight = (*itVecIter)->weight;
    itVecIter = vecIter.erase(itVecIter);  
}

通过gdb的运行时调用堆栈为

(gdb) bt
#0  Dict::DATrieT<unsigned short, std::vector<unsigned short, std::allocator<unsigned short> >, std::vector<int, std::allocator<int> > >::buildTrie (this=0x7fffffffd8f8, vkey_code=std::vector of length 125163, capacity 131072 = {...}, 
trie=std::vector of length 31422, capacity 31422 = {...}) at ./tools/Dict/Datrie.cpp:467
#1  0x0000000000602759 in Dict::DATrieT<unsigned short, std::vector<unsigned short, std::allocator<unsigned short> >, std::vector<int, std::allocator<int> > >::build (this=0x7fffffffd8f8, vkey_code=std::vector of length 125163, capacity 131072 = {...})
at ./tools/Dict/Datrie.cpp:178
#2  0x0000000000602104 in Loader::Trie_Loader::InnerLoad (this=0x7fffffffd8e0, dictPtrs=...) at loader//Trie_Loader.cpp:116
#3  0x0000000000473ba7 in deduce::DeduceClassify::Get_Dat_EntityRec (this=0xa2fb28) at Classification/Deduce//DeduceClassify.cpp:500
#4  0x0000000000470d7b in deduce::DeduceClassify::init (this=0xa2fb28, base_Path="..//data/", 
qp_dict=std::shared_ptr (count 2, weak 0) 0x1bc14600, tokenizer=0xa2f998, indexer=0xf6efb0, pNormer=0xa2f898)
at Classification/Deduce//DeduceClassify.cpp:53
#5  0x000000000040e785 in queryparser::CQueryParserImpl::Init (this=0xa2f4a0, dataPath="../") at QueryParserImpl.cpp:120
#6  0x000000000043ca92 in main_process::test_main (argc=2, argv=0x7fffffffdd20) at MainProcess.cpp:284
#7  0x00000000006301ae in main (argc=3, argv=0x7fffffffde38) at main.cpp:57

我在Datrie.cpp中使用了模板类。而且我不确定为什么使用

进行矢量分配

treeNode.weight =(* itVecIter)->权重;

有内存泄漏。

谢谢。

2 个答案:

答案 0 :(得分:0)

似乎调用了treeNode.weight的赋值运算符,它分配了一些要使用的内存,但从未取消分配。

==37533==    by 0x48B73F: int* std::vector<int, std::allocator<int> >::_M_allocate_and_copy<__gnu_cxx::__normal_iterator<int const*, std::vector<int, std::allocator<int> > > >(unsigned long, __gnu_cxx::__normal_iterator<int const*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int const*, std::vector<int, std::allocator<int> > >) (stl_vector.h:1224)
==37533==    by 0x48B2BD: std::vector<int, std::allocator<int> >::operator=(std::vector<int, std::allocator<int> > const&) (vector.tcc:195)

答案 1 :(得分:0)

按照@ n.m。的建议,我已经检查了整个代码。我想我找到了问题。简化了以下类的构造函数/析构函数和操作:

#include <iostream>                                 
#include <vector>                                 
#include <string.h>                                 
using namespace std;                                

struct leak_struct {
    vector<string> array;
    int set;
};

int main(){                                
    leak_struct ls;                                

    ls.array.push_back("hello");                                
    ls.array.push_back("world");                                

    memset(&ls, 0, sizeof(ls));

    ls.array.push_back("code");                                
    ls.array.push_back("review");                                

    memset(&ls, 0, sizeof(ls));
    return 0;                                
}    

它泄漏的原因是在调用memset的那一行,此调用将使struct中的向量指针无效,并使新分配的缓冲区不被释放。