我得到了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会抱怨如果没有泄漏。我仍然在为这个问题找到更好/更干净的解决方案。
答案 0 :(得分:3)
通过调用exit()
函数退出C ++程序时,不会运行对象析构函数。这可能导致Valgrind报告内存泄漏。
答案 1 :(得分:1)
我知道这已经快一年了但是我找到了这个专门针对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 ++一个月一半,所以我不是真正的专家。
答案 2 :(得分:0)
也许有问题的C ++类正在用指针做一些事情,这些指针表明Valgrind可能会出现泄漏行为。
我在一个项目中对此进行了诊断,我在其中分配了一些数组,但随后我将指针调整到第三个元素,以便使用indices [-2]和[-1]来存储一些元信息。没有泄漏,因为我恢复指针并正确释放数组。
Valgrind看到对象被引用,但是它们不是通过指向它们的基地址的“很好”引用,而是仅通过内部指针引用。它看起来像是一个可能的泄漏,因为没有用于释放对象的指针。
这样的情况可能发生在漏洞程序中:例如,分配一个大对象的程序,将它的一部分(通过指针)提供给其他模块,然后泄漏大对象。内部指针确实表明泄漏。
getline
可能是basic::string<>
与{{1}}的表现形式相似并做某种事情。复制对象时,新对象不会做任何有趣的事情:它只是通过其基地址引用字符串数据。旧对象消失了,它释放了数据。
只是一个假设。
顺便说一句,在上述程序中,我通过在管理这些数组的向量对象中保留一个指向基址的额外指针来修复Valgrind的内容。只有在为Valgrind调试构建软件时(以及其他功能,如使用Valgrind客户端请求API),才会出现此额外指针。