【问题标题】:getline() valgrind memory leakgetline() valgrind 内存泄漏
【发布时间】:2014-04-09 20:21:48
【问题描述】:

我在使用 getline 时遇到内存泄漏,我不知道为什么或如何阻止它。

这是来自 valgrind 的报告:

==26681==
==26681== HEAP SUMMARY:
==26681==     in use at exit: 1,756 bytes in 73 blocks
==26681==   total heap usage: 223 allocs, 150 frees, 15,523 bytes allocated
==26681==
==26681== 28 bytes in 1 blocks are possibly lost in loss record 1 of 4
==26681==    at 0x4A075BC: operator new(unsigned long) (vg_replace_malloc.c:298)
==26681==    by 0x4CCC4B8: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (new_allocator.h:94)
==26681==    by 0x4CCD227: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (basic_string.tcc:631)
==26681==    by 0x4CCD30F: std::string::reserve(unsigned long) (basic_string.tcc:512)
==26681==    by 0x4CCD5D4: std::string::append(char const*, unsigned long) (basic_string.tcc:310)
==26681==    by 0x4C86384: std::basic_istream<char, std::char_traits<char> >& std::getline<char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char) (istream.cc:397)
==26681==    by 0x4026ED: main (test.cpp:210)
==26681==
==26681== LEAK SUMMARY:
==26681==    definitely lost: 0 bytes in 0 blocks
==26681==    indirectly lost: 0 bytes in 0 blocks
==26681==      possibly lost: 28 bytes in 1 blocks
==26681==    still reachable: 1,728 bytes in 72 blocks
==26681==         suppressed: 0 bytes in 0 blocks
==26681== Reachable blocks (those to which a pointer was found) are not shown.
==26681== To see them, rerun with: --leak-check=full --show-reachable=yes
==26681==
==26681== For counts of detected and suppressed errors, rerun with: -v
==26681== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)

这是 test.cpp 的第 210 行

bool pending = getline(inputfile, line);

还有几行:

string line;

bool pending = getline(inputfile, line);
int round = readOption(inputfile);
int num  = readOption(inputfile);

我认为它与 getline 失败有关,并且因为 line 是 string 它以某种方式永远不会释放该内存。我该如何防止这种情况?

readOption 也使用getline,但我认为它没有内存泄漏,因为string line 是在本地定义的,然后超出范围,有效地清理了内存?

编辑 1:

我已经通过创建一个虚拟函数“解决”了这个问题:

bool getnewline(ifstream &inputfile) {
    string line;
    return getline(inputfile, line);
}

但是这样做似乎很愚蠢,我不确定为什么 valgrind 会抱怨如果没有泄漏。我仍在寻求更好/更干净的解决方案。

【问题讨论】:

  • 您显示的所有变量都有自动存储期限。它们不能泄漏。
  • 我不知道怎么理解 valgrind 的抱怨
  • 我今天已经看到了这个(几乎)相同的问题......
  • 鉴于该块“可能丢失”,它也可能“可能未丢失”,并且您的代码表明“未丢失”是正确的。我不确定我是否会相信这两种分析,但这就是表面上的意思。我建议查看其他三个损失记录,并在可能的情况下修复这些记录。您最终可能会创建一个抑制 - 但要谨慎这样做。您需要通过运行许多使用getline() 并报告基本相同的“可能丢失”错误的程序来验证它是否有必要。如果只有这个程序触发了错误,那很可能是你的程序。
  • valgrind 错误/警告摘要怎么说 BTW?

标签: c++ string memory-leaks valgrind getline


【解决方案1】:

当您通过调用 exit() 函数退出 C++ 程序时,不会运行对象析构函数。这可能会导致 Valgrind 报告内存泄漏。

【讨论】:

    【解决方案2】:

    我知道这已经快一年了,但我找到了这个答案,专门寻找 getline() 内存泄漏问题,并想就如何重现这个特定问题给出最低限度的说明,因为我认为它刚刚出现从定义一个 std::string 变量而不是从程序中干净地退出。

    鉴于以下情况:

    leaky.cpp:

    #include <iostream>
    int main(int argc, char ** argv) {
        std::string x = "x";
        exit(1);
        return 0;
    }
    

    编译字符串:

    g++ -g -Wall -Wpedantic --std=gnu++11 leaky.cpp -o leaky
    

    Valgrind 调用:

    valgrind --tool=memcheck --leak-check=full ./leaky
    

    这样做会发现确实存在泄漏:

    ==4434== Memcheck, a memory error detector
    ==4434== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
    ==4434== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
    ==4434== Command: ./leaky
    ==4434== 
    ==4434== 
    ==4434== HEAP SUMMARY:
    ==4434==     in use at exit: 16 bytes in 1 blocks
    ==4434==   total heap usage: 1 allocs, 0 frees, 16 bytes allocated
    ==4434== 
    ==4434== 16 bytes in 1 blocks are possibly lost in loss record 1 of 1
    ==4434==    at 0x402A6DC: operator new(unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
    ==4434==    by 0x40F8213: std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.19)
    ==4434==    by 0x40FA125: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.19)
    ==4434==    by 0x40FA7AF: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.19)
    ==4434==    by 0x804875E: main (leaky.cpp:3)
    ==4434== 
    ==4434== LEAK SUMMARY:
    ==4434==    definitely lost: 0 bytes in 0 blocks
    ==4434==    indirectly lost: 0 bytes in 0 blocks
    ==4434==      possibly lost: 16 bytes in 1 blocks
    ==4434==    still reachable: 0 bytes in 0 blocks
    ==4434==         suppressed: 0 bytes in 0 blocks
    ==4434== 
    ==4434== For counts of detected and suppressed errors, rerun with: -v
    ==4434== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
    

    当然,要尝试包含问题的答案,exit(1) 会强制程序退出而不调用任何析构函数,据我所知——我只使用 C++ 一个半月,所以我不是真正的专家。

    【讨论】:

      【解决方案3】:

      也许有问题的 C++ 类正在使用指向 Valgrind 可能存在泄漏行为的指针做某事。

      我在分配了一些数组的项目中对此进行了诊断,但随后我调整了指向第三个元素的指针,以便使用索引 [-2] 和 [-1] 来存储一些元信息。没有泄漏,因为我恢复了指针并正确释放了数组。

      Valgrind 看到对象被引用,但是,它们不是通过指向其基地址的指针“很好地”引用,而只是通过内部指针。看起来可能存在泄漏,因为不存在用于释放对象的指针。

      这样的情况可能发生在泄漏程序中:例如,分配一个大对象,将它的一部分(通过指针)提供给其他模块,然后泄漏大对象的程序。内部指针确实表明存在泄漏。

      可能是getlinebasic::string&lt;&gt; 的表示很亲密,并且做了类似的事情。当您复制对象时,新对象不会做任何有趣的事情:它只是通过其基地址引用字符串数据。旧对象消失了,它释放了数据。

      只是一个假设。

      顺便说一句,在上述程序中,我通过在管理这些数组的向量对象中保留一个指向基地址的额外指针来为 Valgrind 修复了一些问题。只有在为 Valgrind 调试(以及其他功能,如使用 Valgrind 客户端请求 API)构建软件时,才会出现这个额外的指针。

      【讨论】:

        猜你喜欢
        • 2023-03-25
        • 2013-06-24
        • 2020-03-31
        • 2016-03-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多