0

我已经编写了自己的输入流缓冲区,它应该适用于 gzip 压缩文件。这是它的界面:

class gzstreambuf : public std::streambuf
{
    static const int bufferSize = 8192;

public:
    gzstreambuf();
    ~gzstreambuf();
    int is_open() { return opened_; }
    gzstreambuf* open(const std::string& name, int mode);
    std::streampos pubseekpos(std::streampos offset, std::ios_base::openmode which = std::ios_base::in);
    int underflow();

private:
    void close();

private:
    gzFile            file;
    char              opened;
    char              buffer[bufferSize];
    int               mode;
    std::string       fileName;
};

我正在尝试编写函数,该函数将获取文件名并返回普通的streambuf,以防文件未压缩,否则返回gzstreambuf:

boost::shared_ptr<std::streambuf>
getStreamBuffer(const std::string& fileName)
{
    const bool isGzippedFile = ( fileName.size() >= 3 && ".gz" == fileName.substr(fileName.size() -3));
    std::ifstream is(fileName.c_str());
    boost::shared_ptr<std::streambuf> strBuf;

    if(! isGzippedFile)
    {
        strBuf.reset(is.rdbuf());
    }
    else
    {
        boost::shared_ptr<gzstreambuf> gz(new gzstreambuf);
        gz->open(fileName, std::ios_base::in);
        strBuf = gz;
    }

    return strBuf;
}

但是这个实现在非 gzip 文件的情况下不起作用,因为is对象会在调用这个函数后被销毁。

我该如何解决这个问题?

4

1 回答 1

3

该函数有两个主要问题getStreamBuffer,尽管两者实际上是相同的并且都导致未定义的行为

  1. 您对std::auto_ptr. 然后使用这个智能指针来获取包含在智能指针中的原始指针,只是为了放入另一个智能指针。但是,问题是一旦std::auto_ptr对象超出范围,包含的指针将被删除,因此另一个智能指针现在将指向已删除的对象。

  2. 第二个问题与前一个问题相同,但返回的智能指针。您从中获取原始指针strBuf并将其返回。但是,由于strBuf不是真正共享的,并且它的引用计数器为 1,因此指针一旦strBuf超出范围就会被删除,从而使返回的指针成为指向现在已删除对象的指针。

第一个问题可以通过根本不使用std::auto_ptr或使用例如std::shared_ptr并使用简单赋值来解决strBuf

第二个问题可以通过简单地返回来解决strBuf

于 2014-08-15T08:32:08.900 回答