破坏std :: stringbuf导致访问冲突

时间:2015-04-12 20:05:43

标签: c++ arrays stl buffer access-violation

我有一个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)
    }

};

2 个答案:

答案 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;
}