2012-04-08 13 views
0

Ich habe eine Klasse, die von Std :: streambuf abgeleitet ist. Ich kann nicht verstehen, warum oder wo es ausläuft; entsprechend dem Werkzeug, das ich benutze, ist der letzte Punkt in meinem Code, bevor es aussieht, irgendwo in dieser Klasse (aber es kann Zeilennummer nicht extrahieren)Speicherleck in meiner benutzerdefinierten Streambuf-Klasse

Die Idee ist, dass die Klasse eine beliebige Anzahl von Streambufs halten kann, was es wird Daten in synchronisieren. (Zum Beispiel std :: cout und a ofstream.rdbuf) Ich speichere meine Daten in einer Zeichenkette, bis ich die std :: endl bekomme, in die ich alle streambufs schreibe

Kann mir jemand zeigen, wo es könnte Leckspeicher?

Das ist mein Kopf:

#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-Datei:

#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

wird Ihr streamBuf * dynamisch zugewiesen? Ich sehe einen Aufruf zum Entfernen(), führt dies eine Löschung durch? – EdChum

+0

meinst du mStreambuf-Mitglied oder MyStreamBuf-Klasse? Die hinzugefügten streambufs sind zum Beispiel std :: cout.rdbuf oder ein ofstream.rdbuf (was ich schließe und lösche) – KaiserJohaan

+0

Ich meine was auch immer in 'void MyStreamBug :: RemoveStream (std :: streambuf * sb) 'ist sb dynamisch zugeordnet? Wenn ja, dann sollten Sie es löschen, da remove nur den Eintrag entfernt und nicht die richtige Sache tut, da Sie Zeiger speichern, sonst ist es besser, einen Container zu haben, der 'shared_ptr ' anstelle von rohen Zeigern – EdChum

Antwort

1

Sie sind nicht die streambuf Objekte zu zerstören, also ist es ein klassisches Speicherleck.

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

Beachten Sie, dass dies nicht wirklich eine optimale Lösung, denn mit einem Zeiger auf eine streambuf nicht das Eigentum bedeuten. Zum Beispiel könnte std::cout.rdbuf() etwas sein, das Sie hinzufügen würden, aber nicht etwas, das Sie möchten delete. (Ich weiß nicht, was Ihre Klasse tun soll.)

Sie müssen die Besitz Semantik entscheiden. Entweder MyStreamBuf besitzt alle mStreamBufs, oder es besitzt keine, oder Sie können eine Eigentums-Flag für jeden hinzufügen, aber in jedem Fall muss jeder Besitzer seine Objekte an einem bestimmten Punkt zu zerstören.

+0

Ich hätte es mir entschuldigen müssen, die Klasse besitzt keines der streambufs, also sollte es sie nicht bereinigen – KaiserJohaan

-2

Sind Sie der Meinung, dass std :: streambuf kein virtuelles destructor hat? und tatsächlich Ihr destructor (wenn Sie die dynamische Polymorphie verwenden) nicht Natürlich Elemente mStreamBufs aufgerufen wird nicht wirklich gelöscht ..

+0

also delete auf MyStreamBuf aufrufen, niether ~ MyStreamBuf() noch dessen ~ streambuf wird nicht aufgerufen? – KaiserJohaan

+1

'std :: basic_streambuf' hat einen virtuellen Destruktor, siehe 27.6.3. In der Tat implementiert 'std :: streambuf' keine Funktionalität und könnte leicht eine abstrakte Basisklasse gewesen sein. – Potatoswatter

+0

OK, danke. Normalerweise verwende ich keine Vererbung für Standardklassen (nur Dekomposition), aber in diesem Fall ist es möglich –