我目前正处于调试的内存泄漏检测阶段,并在我的可执行文件上运行valgrind --leak-check=full --show-leak-kinds=all
。但是,我在丢失记录中得到了一些令人困惑的输出:
==26628== 2 bytes in 1 blocks are indirectly lost in loss record 2 of 343
==26628== at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26628== by 0x436EF6: void std::vector<unsigned char, std::allocator<unsigned char> >::_M_range_insert<char*>(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsig$
==26628== by 0x4368EF: giga::Page::aux_load() (stl_vector.h:1291)
==26628== by 0x43499D: cachepp::SerialCache<cachepp::SimpleSerialCacheData, giga::Page>::allocate(std::shared_ptr<giga::Page> const&) (lineinterface.template:34)
...
问题在于giga::Page::aux_load
的跟踪 - 这个函数是由我定义的,而且大多数不是在标准库中。我不确定为什么没有从相应的调用文件在此输出行上报告该行。
我不确定代码是否必要,但如果我这样做 -
void giga::Page::aux_load() {
this->data.clear();
// deallocate the data vector
std::vector<uint8_t>().swap(this->data);
if(!this->get_is_dirty()) {
// load data into the page
FILE *fp = fopen(this->get_filename().c_str(), "r");
if(fseek(fp, this->file_offset, SEEK_SET) == -1) {
throw(exceptionpp::RuntimeError("giga::Page::aux_load", "invalid result returned from fseek"));
}
char *data = (char *) calloc(this->get_size(), sizeof(char));
if(fread((void *) data, sizeof(char), this->get_size(), fp) < this->get_size()) {
throw(exceptionpp::RuntimeError("giga::Page::aux_load", "invalid result returned from fread"));
}
fclose(fp);
this->data.insert(this->data.end(), data, data + this->get_size());
free((void *) data);
}
}
非常感谢任何帮助!
答案 0 :(得分:2)
这很可能是由valgrind stacktrace没有显示内联函数调用引起的 在stl_vector.h:1291中定义并在aux_load内部调用。
下一版Valgrind支持显示内联功能, 使用选项--read-inline-info = yes。
因此,获取并编译最新的valgrind svn版本 见http://www.valgrind.org/downloads/repository.html 有关如何获取,配置和编译valgrind svn版本
的说明答案 1 :(得分:0)
这可能不是您报告中泄漏的原因,但您的代码肯定会泄漏内存,毫无疑问。如果你抛出异常,它会泄漏:
throw(exceptionpp::RuntimeError("giga::Page::aux_load", "invalid result returned from fread"));
泄漏的原因是您先前调用了calloc
,并且从未到达free
数据的行。如果您的函数抛出任何异常,您还有一个悬空的打开文件指针。
纠正这个问题的答案是短暂而甜蜜的:
使用std::ifstream
,而不是FILE*
。这将保证您的文件在函数返回时关闭,无论返回的原因是什么。
使用std::vector<char> dataV(get_size())
,而不是calloc
。这将保证在函数返回时释放内存,无论返回的原因是什么(在这种情况下,使用&dataV[0]
或者如果使用C ++ 11 dataV.data()
来获取指向char缓冲区的指针)。
您应该阅读的主题是RAII:What is meant by Resource Acquisition is Initialization (RAII)?
使用上面的这些结构重写您的代码,您将免除您发布的功能中的泄漏。
您应该使用的其他更改:
检查get_size() == 0
。如果它为0,那么您可以立即返回而无需打开文件。
您无需在任何地方使用this->
。如果出现问题,它会使代码混乱并使调试变得更加困难。