0

gzip 圧縮されたファイルで動作するはずの独自の入力 streambuf を作成しました。そのインターフェースは次のとおりです。

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

ファイルがgzipされていない場合はファイル名を取り、通常の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;
}

isただし、この関数の呼び出し後にオブジェクトが破棄されるため、gzip されていないファイルの場合、この実装は機能しません。

どうすればこれを解決できますか?

4

1 に答える 1

3

getStreamBufferどちらも実際には同じであり、未定義の動作につながるにもかかわらず、関数には2つの大きな問題があります。

  1. の使用std::auto_ptr。次に、このスマート ポインターを使用して、スマート ポインターに含まれる生のポインターを取得し、別のスマート ポインターを挿入します。ただし、問題は、std::auto_ptrオブジェクトが範囲外になると、含まれているポインターが削除されるため、他のスマート ポインターが削除されたオブジェクトを指すようになることです。

  2. 2 番目の問題は前と同じですが、スマート ポインターが返されます。生のポインターを取得してstrBuf返します。ただし、strBufは実際には共有されておらず、その参照カウンターは 1 であるため、ポインターはstrBufスコープ外になると削除され、返されるポインターは削除されたオブジェクトへのポインターになります。

std::auto_ptr最初の問題は、まったく使用しないか、 egstd::shared_ptrを使用して への単純な代入を使用することで解決できますstrBuf

2 番目の問題は、 を返すだけで解決できますstrBuf

于 2014-08-15T08:32:08.900 に答える