2012-04-08 51 views
0

我有一个派生自std :: streambuf的类。我不知道为什么或在哪里泄漏,但;根据我正在使用的工具,我的代码中的最后一点看起来是在这个类的某个地方(但它不能提取行号)我的自定义streambuf类中的内存泄漏

这个想法是,该类可以容纳任何数量的streambufs它会将数据同步到。 (例如,std :: cout和ofstream.rdbuf)我将我的数据存储在一个字符串中,直到我得到std :: endl,我在其中写入所有streambuf

任何人都可以指向我可以在哪里泄漏内存?

这是我的头:

#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; 
    } 
} 
+1

是你的streamBuf *动态分配的吗?我看到一个调用remove(),这是否执行删除? – EdChum 2012-04-08 22:22:02

+0

你是指mStreambuf成员还是MyStreamBuf类?添加的streambufs是例如std :: cout.rdbuf或ofstream.rdbuf(我关闭并删除) – KaiserJohaan 2012-04-08 22:34:17

+0

我的意思是任何被传入'无效MyStreamBug :: RemoveStream(std :: streambuf * sb)'是sb动态分配?如果是这样,那么你应该删除它作为删除只是删除条目,而不是做适当的事情,因为你正在存储指针,否则最好有一个容器存储'shared_ptr '而不是原始指针 – EdChum 2012-04-08 22:36:46

回答

1

你是不是破坏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,也可以不拥有任何一个,也可以为每个拥有者标记添加一个所有权标记,但是在任何情况下,每个所有者都需要在某个点销毁其对象。

+0

我应该写下它,抱​​歉,类没有任何streambuf,因此它不应该清理它们 – KaiserJohaan 2012-04-09 09:42:20

-2

你认为性病::流缓冲没有虚析构函数?实际上(如果你使用动态多态性)你的析构函数不会被调用 mStreamBufs真的不删当然元素中..

+0

所以调用MyStreamBuf上的删除,niether〜MyStreamBuf()和其〜streambuf将不会被调用? – KaiserJohaan 2012-04-08 22:45:09

+1

'std :: basic_streambuf'确实有一个虚拟析构函数,见27.6.3。实际上'std :: streambuf'没有实现任何功能,并且很容易成为一个抽象基类。 – Potatoswatter 2012-04-09 02:42:48

+0

好的,谢谢。通常我不会为标准类使用继承(只能分解),但在这种情况下,可能会有 – 2012-04-10 05:05:10