0

我有两个类,一个继承自ostream,另一个继承自streambuf,这就是我使用它们的方式

int main () {
   stampstream ss(8,10);
}

戳流

stampstream::stampstream(int r, int c) : ostream(new stampbuf(r,c))
{
   std::cout << "I am in stampstream" << std::endl;
}

我只是调用父(ostream)类ctor并在参数中创建stampbuf类的对象。

印花税

stampbuf::stampbuf(int r, int c)
: _row(0), _column(0), BUFFER_SIZE(10), _buffer(new char[BUFFER_SIZE]) 
{ //some code }

所以当我在我的项目上运行 Valgrind 时,它说我有 106 字节的内存泄漏。其中96个来自new stampbuf(r,c),10个来自_buffer(new char[BUFFER_SIZE])

我有用于释放内存的 stampbuf 的析构函数delete_buffer然而,析构函数永远不会被调用。如何摆脱这种内存泄漏并为stampbuf调用析构函数?

编辑

class stampstream : public ostream {

public:
stampstream(int r, int c);
virtual ~stampstream();
};

class stampbuf : public streambuf {

 public:
stampbuf(int r, int c);
~stampbuf();
virtual int overflow(int ch);
    };
4

3 回答 3

5

你需要打电话

delete ostream;

在和的析构函数stampstream

delete[] _buffer;

stampbuf.

你最好使用std::unique_ptrfor ostream, a std::vectorfor_buffer,而且你不需要担心内存管理。另外,ostream是一个名字std,我建议你在为时已晚之前重命名你的变量。

于 2012-10-16T07:54:11.777 回答
2

您可以按如下方式删除它:

stampstream::~stampstream()
{
    delete rdbuf();
}

然而,这并不安全。由于用户stampstream可以(并且有权)更改rdbuf,它可能会导致未定义的行为。

惯用的方法是拥有派生类的相应streambuf成员ostream,从而避免任何动态内存分配。

class stampstream : public ostream {
public:
    // ...
private:
    stampbuf sb;
};

stampstream::stampstream(int r, int c) : ostream(&sb)
{
    // ...
}

// nothing to delete in the destructor...
于 2012-10-16T08:12:37.493 回答
-1

问题是 ostream 没有在其析构函数中清理流缓冲区:

http://www.cplusplus.com/reference/iostream/ostream/~ostream/

[...] 请注意,它不会破坏或对关联的 streambuf 对象执行任何操作。

所以你必须在其他地方清理streambuf。最简单的方法是让你的 stampbuf 对象成为 stampstream 的成员变量——然后当你的 stampstream 被破坏时,它的析构函数会被自动调用。

基类 ostream 的构造函数在构造成员变量之前被调用,因此如果您将 stampbuf 对象作为参数传递给 ostream 构造函数,ostream 的构造函数最终会查看未构造的 stampbuf 对象。因此,不要将流缓冲区传递给构造函数,而是在构造函数中设置它,在使用 rdbuf 构造 stampbuf 之后:

http://www.cplusplus.com/reference/iostream/ios/rdbuf/

这提出了您的 stampbuf 在基类之前被破坏的问题,因此 ostream 的析构函数将查看解构的 stampbuf。这通常是不可接受的,但是因为上面的 ~ostream 页面保证 ~ostream 不对流缓冲区做任何事情,所以在这种情况下很好。

于 2012-10-16T08:31:21.860 回答