Valgrind内存泄漏错误的文件跟踪

时间:2014-08-24 06:01:49

标签: c++ valgrind

我目前正处于调试的内存泄漏检测阶段,并在我的可执行文件上运行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);
    }
}

非常感谢任何帮助!

2 个答案:

答案 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数据的行。如果您的函数抛出任何异常,您还有一个悬空的打开文件指针。

纠正这个问题的答案是短暂而甜蜜的:

  1. 使用std::ifstream,而不是FILE*。这将保证您的文件在函数返回时关闭,无论返回的原因是什么。

  2. 使用std::vector<char> dataV(get_size()),而不是calloc。这将保证在函数返回时释放内存,无论返回的原因是什么(在这种情况下,使用&dataV[0]或者如果使用C ++ 11 dataV.data()来获取指向char缓冲区的指针)。

  3. 您应该阅读的主题是RAII:What is meant by Resource Acquisition is Initialization (RAII)?

    使用上面的这些结构重写您的代码,您将免除您发布的功能中的泄漏。

    您应该使用的其他更改:

    1. 检查get_size() == 0。如果它为0,那么您可以立即返回而无需打开文件。

    2. 您无需在任何地方使用this->。如果出现问题,它会使代码混乱并使调试变得更加困难。