【问题标题】:Memory leak in my custom streambuf class我的自定义 streambuf 类中的内存泄漏
【发布时间】:2012-04-21 11:01:02
【问题描述】:

我有一个派生自 std::streambuf 的类。我无法弄清楚它为什么或在哪里泄漏;根据我使用的工具,我的代码在它看起来之前的最后一点是在这个类的某个地方(但它不能提取行号)

这个想法是,该类可以保存将数据同步到的任意数量的流缓冲区。 (例如,std::cout 和 a ofstream.rdbuf)我将数据存储在一个字符串中,直到我得到 std::endl,在其中我写入所有的 streambufs

谁能指出它可能泄漏内存的地方?

这是我的标题:

#ifndef _MY_STREAM_BUF_H
#define _MY_STREAM_BUF_H

#include <iostream>
#include <algorithm>
#include <list>

#include "../../../Interface/EngineDefs.h"

namespace MyEngine
{
    class MyStreamBuf : public std::streambuf
    {
    public:
        MyStreamBuf();
        ~MyStreamBuf();

        void AddStream(std::streambuf* sb);
        void RemoveStream(std::streambuf* sb);
        bool IsStreamAdded(std::streambuf* sb);

    private:
        std::list<std::streambuf*> mStreamBufs;
        std::string mLine;

        int32_t overflow(int32_t c);
        int32_t sync();

    };
}

#endif

cpp 文件:

#include "../../../Include/Core/Logging/MyStreamBuf.h"

namespace MyEngine
{
    MyStreamBuf::MyStreamBuf() : std::streambuf()
    {

    }

    MyStreamBuf::~MyStreamBuf()
    {
        mStreamBufs.clear();
        mLine.clear();
    }

    void MyStreamBuf::AddStream(std::streambuf* sb)
    {
        if (sb)
            mStreamBufs.push_back(sb);
    }

    void MyStreamBuf::RemoveStream(std::streambuf* sb)
    {
        if (sb)
            mStreamBufs.remove(sb);
    }

    bool MyStreamBuf::IsStreamAdded(std::streambuf* sb)
    {
        if (sb)
            return (std::find(mStreamBufs.begin(),mStreamBufs.end(),sb) != mStreamBufs.end());
        else
            return false;
    }

    int32_t MyStreamBuf::overflow(int32_t c)
    {
        int32_t r1 = 0, r2 = 0;

        if (c == EOF)
           return !EOF;
        else
        {
            mLine += c;
            return r1 == EOF || r2 == EOF ? EOF : c;
        }
    }

    int32_t MyStreamBuf::sync()
    {
        int32_t res = 0;

        for(std::list<std::streambuf*>::iterator it = mStreamBufs.begin(); it != mStreamBufs.end(); ++it)
        {
            if (*it)
            {
                (*it)->sputn(mLine.c_str(),mLine.length());
                res &= (*it)->pubsync();
            }
        }               

        mLine.clear();

        return res == 0 ? 0 : -1;
    }
}

【问题讨论】:

  • 您的 streamBuf* 是动态分配的吗?我看到一个对 remove() 的调用,这会执行删除吗?
  • 您是指 mStreambuf 成员还是 MyStreamBuf 类?添加的流缓冲区例如 std::cout.rdbuf 或 ofstream.rdbuf (我关闭并删除)
  • 我的意思是传递给void MyStreamBug::RemoveStream(std::streambuf* sb)的任何东西都是动态分配的?如果是这样,那么您应该删除它,因为 remove 只是删除条目而不是在存储指针时执行适当的操作,否则最好有一个容器存储 shared_ptr&lt;std::streambuf*&gt; 而不是原始指针
  • 是的,例如 std::ofstream,我正在正确分配/解除分配
  • 它在哪里被释放,我只看到对remove() 的调用而没有对应的delete?你可以做的另一件事是使用windbg,使用gflags在你的应用程序上启用用户堆栈跟踪,然后用windbg将它附加到你的应用程序,输入.symfix;.reload;!heap -l;它应该告诉你它认为泄漏在哪里或在下面运行你的应用程序Visual Studio 并在检测到泄漏时附加 Windbg,请参阅cfc.kizzx2.com/index.php/…

标签: c++ memory-management memory-leaks iostream


【解决方案1】:

你认为 std::streambuf 没有虚拟析构函数吗?实际上(如果你将使用动态多态性)你的析构函数不会被调用 当然mStreamBufs的元素真的没有被删除..

【讨论】:

  • 所以在 MyStreamBuf 上调用 delete,既不会调用 ~MyStreamBuf() 也不会调用它的 ~streambuf?
  • std::basic_streambuf 确实有一个虚拟析构函数,见 27.6.3。事实上std::streambuf 没有实现任何功能,很容易成为一个抽象基类。
  • 好的,谢谢。通常我不会对标准类使用继承(仅分解),但在这种情况下它是可能的
【解决方案2】:

您没有销毁 streambuf 对象,因此这是典型的内存泄漏。

void MyStreamBuf::RemoveStream(std::streambuf* sb)
{
    delete sb; // need this to flush and avoid leak

    if (sb) // do you really need to check if it's null?
        mStreamBufs.remove(sb);
}

请注意,这并不是真正的最佳解决方案,因为拥有指向 streambuf 的指针并不意味着拥有所有权。例如,std::cout.rdbuf() 可能是您要添加的内容,但不是您想要添加的内容 delete。 (我不知道你的班级应该做什么。)

您需要确定所有权语义。 MyStreamBuf 拥有所有 mStreamBufs,或者它不拥有任何东西,或者您可以为每个 MyStreamBuf 添加所有权标志,但在任何情况下,每个所有者都需要在某个时候销毁其对象。

【讨论】:

  • 对不起,该类不拥有任何流缓冲区,因此不应清理它们
猜你喜欢
  • 2018-07-15
  • 1970-01-01
  • 2017-08-24
  • 1970-01-01
  • 1970-01-01
  • 2011-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多