如何解决 STL 字符串中报告的内存泄漏问题?

发布于 2024-11-19 20:38:10 字数 3900 浏览 3 评论 0原文

对于学校项目,我们必须通过网络发送大文件,我们必须使用 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

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

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


编辑:

我在 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 >

For a school project, we have to send big files across the network., we must use Poco::XML for our data.

After our files are send over the network, it appears that the memory does not free.

Here is an example for a file of ~9 Mb on the receiving part:

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

 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

The function which is right before Poco is

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;
}

which calls

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

(Note that XMLString is std::string)

Why is the append of STL string leaking memory?

If I just assign instead of using the copy constructors it gives the same problem.


EDIT:

I'm using the latest stable GNU GCC 4.4.4 on Gentoo x64 (linux-2.6.34-gentoo-r12).

More functions from the call stack (stripped irrelevant big chunks of code / if structures):

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);
}

and

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

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

        delete command;
}

and

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

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

    delete prio;
}

where fQueue is:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我早已燃尽 2024-11-26 20:38:10

我想对此发表评论,但显然我没有代表。您是否记得将 Command 的析构函数设为虚拟?如果 namedataPutCommand 的字段,而不是 CommandCommand 析构函数不是虚拟的,当您删除handleClientPacket中的command时,它们可能无法正确释放。

I would make this a comment, but apparently I don't have the rep. Have you remembered to make the destructor for Command virtual? If name or data are fields of PutCommand rather than Command and the Command destructor is not virtual, they may not be freed properly when you delete command in handleClientPacket.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文