KaiserJohaan
KaiserJohaan

Reputation: 9240

Memory leak in my custom streambuf class

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

Answers (2)

Potatoswatter
Potatoswatter

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

Alexander Petrov
Alexander Petrov

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

Related Questions