我使用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) - >重量;
有内存泄漏。
谢谢。
似乎调用了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)
正如@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中的向量指针无效并使新分配的缓冲区不被释放。