Reputation: 9240
I have a class that derives from std::streambuf. I cannot figure why or where it leaks though; according to the tool I'm using, the last point in my code before it looks is somewhere in this class (but it cannot extract line number)
The idea is that the class can hold any number of streambufs which it will sync data into. (For example, std::cout and a ofstream.rdbuf) I store my data in a string untill I get the std::endl, in which I write to all the streambufs
Can anyone point me to where it could leak memory?
This is my header:
#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 file:
#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;
}
}
Upvotes: 0
Views: 940
Reputation: 137860
You aren't destroying the streambuf
objects, so it's a classic memory leak.
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);
}
Note that this isn't really an optimal solution, because having a pointer to a streambuf
does not imply ownership. For example, std::cout.rdbuf()
might be something you would add but not something you would want to delete
. (I don't know what your class is supposed to do.)
You need to decide the ownership semantics. Either MyStreamBuf
owns all the mStreamBufs
, or it owns none, or you might add an ownership flag for each, but in any case every owner needs to destroy its objects at some point.
Upvotes: 1
Reputation: 107
Do you consider that std::streambuf has no virtual destructor? and actually (if you will use dynamic polymorphism) your destructor won't be called Of course elements of mStreamBufs really not deleted..
Upvotes: -2