我有一个c ++类,大致看起来像这样(见下面的代码)。它有一个输入缓冲区和一个使用std :: stringbuf的输出缓冲区。因为我也想访问原始缓冲区,所以我使用std :: stringbuf.pubsetbuf()用我自己的用户定义的字节数组设置底层缓冲区。
所有东西似乎工作正常,直到我不再需要该对象,但是当对象被破坏时,它会导致我的程序因访问冲突而崩溃。
我将其追溯到如下图所示的代码段。它在我看来stringbuf以某种方式清理我的用户定义的字节数组本身?当我删除我的类的destrcutor中的代码以释放我之前在构造函数中分配的字节数组时,我的程序不会崩溃。
对此有任何建议吗?我错误地使用了std :: stringbuf吗?我正在使用Borland 5.0编译器(我知道它是一个非常陈旧且过时的编译器,但我必须坚持使用这个编译器一段时间。)
class SomeClass {
private:
char *mIBuf;
char *mOBuf;
std::stringbuf mIBufStream;
std::stringbuf mOBufStream;
public:
SomeClass(int iBufSize, int oBufSize) :
mIBuf(), mOBuf(),
mIBufStream(), mOBufStream()
{
mIBuf = (char*)malloc(iBufSize);
mOBuf = (char*)malloc(oBufSize);
mIBufStream.pubsetbuf(mIBuf, iBufSize);
mIBufStream.pubseekpos(0);
mOBufStream.pubsetbuf(mOBuf, oBufSize);
mOBufStream.pubseekpos(0);
}
virtual ~SomeClass()
{
free(mIBuf);
free(mOBuf)
}
};
答案 0 :(得分:1)
根据标准stringbuf
没有自己的析构函数,streambuf
的析构函数什么都不做。您的旧编译器和库可能会也可能不会遵循这一点;证据确实不是。
嗯,原则上你做错了什么。当您调用pubsetbuf
时,只要对象存在,或者直到您再次更改其缓冲区,就会授予该对象使用该缓冲区的权限。
看着你的析构函数,你不会保持廉价。
virtual ~SomeClass()
{
free(mIBuf);
free(mOBuf); // <- missing semicolon in your code
// the stringbuf objects are still alive here
} // they get automatically destroyed here
一种选择是在释放缓冲区之前安排stringbuf
对象被销毁(char*
缓冲区释放需要由辅助类(基类或声明的成员)完成在stringbuf
- std::vector<char>
之前是个不错的选择。
或者,您可以让stringbuf
知道您正在撤销其使用记忆的权限:
virtual ~SomeClass()
{
mIBufStream.pubsetbuf(0, 0);
mOBufStream.pubsetbuf(0, 0);
// the stringbufs cannot use your memory any longer
free(mIBuf);
free(mOBuf);
}
答案 1 :(得分:0)
好吧,回答我自己的问题......(并感谢Ben Voight的有用建议)。在其他人证明我错了之前,我已经得出结论,我的问题是特定于实现的,并且Borland 5.0 STL库可能不符合标准。
我测试了我的示例类。我解压缩并将其放入下面列出的小型测试程序中(没有其他可能会破坏内存的代码)。我用Visual Studio 2013编译了1个版本,用Borland 5.0编译了另一个版本。用Visual Studio编译的那个运行得很好。第一次迭代后,用Borland编译的那个崩溃了。
#include <iostream>
class SomeClass {
char *mIBuf;
char *mOBuf;
std::stringbuf mIBufStream;
std::stringbuf mOBufStream;
公共:
SomeClass(int iBufSize, int oBufSize) : mIBuf(NULL), mOBuf(NULL), mIBufStream(), mOBufStream() {
mIBuf = (char*)malloc(iBufSize);
mOBuf = (char*)malloc(oBufSize);
mIBufStream.pubsetbuf(mIBuf, iBufSize);
mIBufStream.pubseekpos(0);
mOBufStream.pubsetbuf(mOBuf, oBufSize);
mOBufStream.pubseekpos(0);
}
virtual ~SomeClass() {
mIBufStream.pubsetbuf(0, 0);
mOBufStream.pubsetbuf(0, 0);
free(mIBuf);
free(mOBuf);
}
};
int main(int argc, char* argv[])
{
for (int x = 0; x < 1000; x++) {
SomeClass SomeClass(128 * 1024, 128 * 1024);
std::cout << "Pass " << x + 1 << std::endl;
}
return 0;
}