【问题标题】:How do I solve memory leaks that are reported to reside in STL string?如何解决据报告驻留在 STL 字符串中的内存泄漏?
【发布时间】:2011-10-02 09:26:09
【问题描述】:

对于一个学校项目,我们必须通过网络发送大文件。我们的数据必须使用 Poco::XML。

我们的文件通过网络发送后,内存似乎没有释放。

以下是接收方~9 Mb文件的示例:

valgrind --leak-check=full --show-reachable=yes -v ourExecutable parms 返回:

 12,880,736 bytes in 37 blocks are definitely lost in loss record 101 of 101
    at 0x4C2747E: operator new(unsigned long) (vg_replace_malloc.c:261)
    by 0x5A3AC88: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6.0.13)
    by 0x5A3BC4A: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6.0.13)
    by 0x5A3C1BB: std::string::reserve(unsigned long) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6.0.13)
    by 0x5A3C68E: std::string::append(std::string const&) (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6.0.13)
    by 0x5202359: Poco::XML::Element::innerText() const (in /home/tomwij/IGS/trunk/Project/external/lib/libPocoXML.so.8)
    by 0x4145BF: NodeProtocol::getChildNodeStrValue(Poco::XML::Element*, std::string) (NodeProtocol.cpp:82)
    by 0x41544F: NodeProtocol::deserialize(std::string const&) (NodeProtocol.cpp:200)
    by 0x40B088: Node::handleClientPacket(PriorityElement*) (Node.cpp:760)
    by 0x40A04C: Node::handlePackets() (Node.cpp:574)
    by 0x4078EA: Node::run() (Node.cpp:162)
    by 0x40772D: Node::activate() (Node.cpp:138)

 LEAK SUMMARY:
    definitely lost: 12,888,036 bytes in 190 blocks
    indirectly lost: 644,979 bytes in 1,355 blocks
      possibly lost: 10,089 bytes in 27 blocks
    still reachable: 306,020 bytes in 43 blocks
         suppressed: 0 bytes in 0 blocks

Poco 之前的函数是

const string NodeProtocol::getChildNodeStrValue(Element * elem, string child)
{
    Element*  tempNode = elem->getChildElement(child);
    XMLString result(tempNode->innerText());
    string ret = string(fromXMLString(result));
    result.clear();
    return ret;
}

哪个调用

XMLString Element::innerText() const
{
    XMLString result;
    Node* pChild = firstChild();
    while (pChild)
    {
        result.append(pChild->innerText());
        pChild = pChild->nextSibling();
    }
    return result;
}

(注意XMLStringstd::string

为什么STL字符串的append会泄漏内存?

如果我只是分配而不是使用复制构造函数,它会产生同样的问题。


编辑:

我在 Gentoo x64 (linux-2.6.34-gentoo-r12) 上使用最新的稳定版 GNU GCC 4.4.4。

调用堆栈中的更多函数(剥离不相关的大块代码/if 结构):

Command * NodeProtocol::deserialize(const string & msg)
{
    DOMParser xmlParser;

    // Get the root node.
    AutoPtr<Document> doc = xmlParser.parseString(msg);
    AutoPtr<Element> rootElement = doc->documentElement();

    string root = fromXMLString(rootElement->nodeName());
    string name = getChildNodeStrValue(rootElement, "name");
    string data = getChildNodeStrValue(rootElement, "data");
    return new PutCommand(name, data);
}

void Node::handleClientPacket(PriorityElement * prio)
{
        Command * command = NodeProtocol::deserialize(prio->fPacket);

        // CUT: Access some properties of command, let the command execute.

        delete command;
}

void Node::handlePackets()
{
    PriorityElement * prio = fQueue->top();
    fQueue->pop();

    if (prio->fSource == kCLIENT)
        handleClientPacket(prio);
    else if (prio->fSource == kNODE)
        handleNodePacket(prio);

    delete prio;
}

fQueue 在哪里:

priority_queue< PriorityElement*,  vector<PriorityElement*>, ComparisonFunction >

【问题讨论】:

  • 您没有在调用堆栈中显示OurExecutable::handleClientPacket 函数的代码,或者上面的任何代码。您发布的代码中没有一个函数显示任何动态分配。所以泄漏不可能存在。
  • 你自己做动态内存分配吗?
  • 使用什么编译器(及其版本)?使用什么标准库实现?
  • @MartinhoFernandes:您是否 100% 认为它不在 Poco 中?我添加了更多信息。
  • @Marlon: 是的,除了deserialize 中的 AutoPtr 我有;我添加了更多信息。

标签: c++ string stl valgrind poco-libraries


【解决方案1】:

我会对此发表评论,但显然我没有代表。你还记得为Command 虚拟化析构函数吗?如果namedataPutCommand 而不是Command 的字段,并且Command 析构函数不是虚拟的,则在删除handleClientPacket 中的command 时可能无法正确释放它们。

【讨论】:

  • 很高兴您没有对此发表评论。显然实际问题似乎离源头很远......:/
  • 经验教训:不一定要看源头,还要看看它的存储位置和发生了什么。
猜你喜欢
  • 2018-07-04
  • 2010-12-26
  • 1970-01-01
  • 2014-05-02
  • 1970-01-01
  • 2015-06-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多