找不到 Valgrind 检测到的内存泄漏

Posted

技术标签:

【中文标题】找不到 Valgrind 检测到的内存泄漏【英文标题】:Can't find memory leak detected by Valgrind 【发布时间】:2013-07-25 18:03:37 【问题描述】:

我正在开发一个程序,但我无法确定内存泄漏。我对 C/C++ 也不是很有经验。我将发布一个 valgrind 错误以及相关的类定义和函数......如果我忘记了什么,请问我会更新:) 我没有发布所有 valgrind 报告的原因是有很多它们,但它们相似......唯一的区别是它具有的堆栈跟踪。

我一开始设计的很糟糕,所以为了修复内存泄漏,我的想法是创建一个全局工厂来添加我的对象,以便以后删除它们。我用工厂方法替换了每次出现的“new”来创建它。在这种情况下,它是 Column 类。我很肯定 makeColumn 创建的每个对象都被删除,因为我使用向量来存储指针。遍历向量并删除其中每个项目的函数在程序结束之前被调用。

这个 valgrind 报告让我觉得不知何故,一个字符串没有被分配。我设置了 GLIBCXX_FORCE_NEW 变量,它对检测到的泄漏没有影响。我正在使用 gcc 4.7.2。

另外,是的,我正在从 ANTLR 生成的解析器接收信息……这可能无关紧要,因为 ANTLR 处理它自己的内存。 char 指针是来自 ANTLR 的唯一数据。

==23168== 15 bytes in 1 blocks are definitely lost in loss record 10 of 30
==23168==    at 0x4ACE73C: operator new(unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==23168==    by 0x4BA62A3: std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) (in /usr/lib32/libstdc++.so.6.0.17)
==23168==    by 0x4BA75EE: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned int) (in /usr/lib32/libstdc++.so.6.0.17)
==23168==    by 0x4BA7F3F: std::string::assign(std::string const&) (in /usr/lib32/libstdc++.so.6.0.17)
==23168==    by 0x4BA7F92: std::string::operator=(std::string const&) (in /usr/lib32/libstdc++.so.6.0.17)
==23168==    by 0x82E0B57: GenericFactory::makeColumn(char const*, char const*, char const*) (global.cpp:246)
==23168==    by 0x82DEA23: addTable (helper.cpp:93)
==23168==    by 0x810DE1F: query_table_expression (OracleSQLParser.c:165181)
==23168==    by 0x8108F66: table_reference (OracleSQLParser.c:162767)
==23168==    by 0x81154B1: join_clause (OracleSQLParser.c:168172)
==23168==    by 0x82A0845: synpred349_OracleSQL_fragment (OracleSQLParser.c:460632)
==23168==    by 0x82AFA48: synpred349_OracleSQL (OracleSQLParser.c:469414)

helper.cpp:addTable - putValue 只是将指针添加到地图。

void addTable(char* schema, char* table) 
    ::gbl_info->tables->putValue(::gbl_info->factory.makeColumn(schema,table,""),NULL);

GenericFactory::makeColumn

Column* GenericFactory::makeColumn(const char* schema,const char* table, const char* column) 
    this->count++;
    Column* col = new Column(schema,table,column);
    this->allocated_objects.push_back(col);
    return col;

列::列

Column::Column(const char* schema, const char* table, const char* column) 
    string temp = schema;
    this->schema = normalize(temp);
    temp = table;
    this->table = normalize(temp);
    temp = column;
    this->column = normalize(temp);
    temp = schema;
    temp = temp + "." + table + "." + column;
    this->text = normalize(temp);

标准化

string& normalize(string& str) 
    for (string::iterator p=str.begin(); p != str.end(); p++)
        *p = toupper(*p);
    str.erase(remove(str.begin(),str.end(),'"'),str.end()); // erase double quotes
    return str;

列定义:SQLData 没有成员或构造函数

class Column : public SQLData 
    std::string text;
    std::string schema;
    std::string table;
    std::string column;
public:
    std::string alias; // TABLE alias
    Column(const char*,const char*,const char*);
    Column(const std::string qn);
    //Has functions too, but probably irrelevant

我已经花了几个小时试图解决这个问题,但我只是不确定我在哪里失去了记忆......程序在处理数据时可以运行几分钟甚至几个小时,因此它确实建立起来了。

【问题讨论】:

你如何确定你有内存泄漏? @Doug 处理 20,000 个项目后,进程大小上升到大约 400 MB……它需要处理数百万个,并且还在继续上升。所以我运行 Valgrind 来找到它们。每个项目之间没有共享——它们之间的所有内存都应该被擦除,因此进程内存占用应该相对较小。 根据我使用 C++ 的经验,几乎每一个“内存泄漏”案例都是由未与 delete 配对的 new 引起的。您是否为正在处理的每一项都致电makeColumn() 【参考方案1】:

解决诸如此类问题(未知来源的错误)的好方法,尝试下载 GCC 并将您的代码扔给“the Wall”。

【讨论】:

谢谢!请参阅下面的我的帖子,了解对此发现的错误的解释(供未来的潜在读者阅读)。【参考方案2】:

好的,所以我想通了。当我使用 -Wall 运行它时,问题就出现了,所以我会接受这个答案:) 这就是问题所在。

虚拟析构函数。不熟悉 C++,我昨天才听说它们……我认为我不需要使用它们,因为我的派生类中实际上没有任何清理代码。错误的!为了在派生类上调用默认析构函数,必须将超类(在本例中为 SQLData)的析构函数声明为虚拟的。因此,我的派生类中没有清理字符串成员,即使它们不是指针。

有趣的是,我不推荐 Cygwin 进行调试。 -Wall 选项在安装的 gcc Cygwin 上没有警告我,但是当我在 Ubuntu 机器上编译时,它会告诉我每个类。

所以,我为修复这个巨大的内存泄漏所做的只是将以下内容添加到我的 SQLData 类定义中:

virtual ~SQLData()  

bam,修复。我不需要为我的任何派生类声明析构函数。

感谢您的帮助!

【讨论】:

很高兴你把它整理好了! :)

以上是关于找不到 Valgrind 检测到的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

Valgrind进行内存泄漏检测

Valgrind C++ 内存泄漏检测

Valgrind C++ 内存泄漏检测

valgrind 检测内存泄漏

valgrind 检测内存泄漏

使用 Valgrind 检测 C++ 内存泄漏