0

私はブーストで練習しており、現在ブースト共有ポインターをテストしています。ファイルを読み取ることができる Util クラスがあります。ファイルを読み取った後、「読み取り」メソッドはファイルの内容を指す boost::shared_ptr を返します。次に、この共有ポインターを Parser クラスに渡します。このクラスは、文字列を 1 行ずつ解析します。解析が完了すると、Parser クラス コンストラクターの最後 ('}') で、ブースト ヘッダー ファイルを指す「ランタイム エラー」が発生します。より具体的には、checked_delete.hpp を「delete x」行に追加します。

template<class T> inline void checked_delete(T * x) {
   // intentionally complex - simplification causes regressions
   typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
   (void) sizeof(type_must_be_complete);
   delete x;
}

単純化されたコードは次のようになります。

class File {
    string _path;
public:
    File(string path)
    ~File()
    void Open();
    boost::shared_ptr<string> Read();
    void Close();
};

class Parse {
public:
    Parse(string path) {
        File file = File(path);
        file.Open();
        boost::shared_ptr<string> fileContentPtr = file.Read();
        StartParsing(fileContentPtr);
        file.Close();
    }
    ~Parse();
    StartParsing(boost::shared_ptr<string> fileContentPtr);
};

int main() {
string path = "<some path to my file>";
Parse(path);
}

誰でも私にヒントを与えることができます、私は何が間違っていますか? 前もって感謝します!

編集: 私の Read() 関数:

boost::shared_ptr<string> File::Read() {
    if(file.is_open()) {
        ostringstream stream;
        stream << file.rdbuf();
        string content = stream.str();
        boost::shared_ptr<string> contentPtr(&content);
        return contentPtr;
    }
    else {
        throw std::runtime_error("File isn't opened");
    }
}

「file」変数は、Open() で使用される std::fstream ファイルです。

4

1 に答える 1

5

に含まれるオブジェクトは、を介して明示的に、または を介し​​て暗黙boost::shared_ptr的に、動的に割り当てる必要があります。から:newboost::make_shared<>boost::shared_ptr

shared_ptr クラス テンプレートは、通常は C++ の new 式を使用して、動的に割り当てられた object へのポインターを格納します。指しているオブジェクトは、それを指している最後の shared_ptr が破棄またはリセットされると、確実に削除されます。

この場合、std::stringインスタンスはスタックに割り当てられ、Read()返されるときに破棄されます。

string content = stream.str();
boost::shared_ptr<string> contentPtr(&content);

これによりshared_ptr、ダングリング ポインターが発生し、 が範囲外にdeleteなったときにポインターが試行され、エラーが発生します。shared_ptr

shared_ptrafterにアクセスしようとするコードRead()はダングリング ポインターを逆参照しているため、プログラムには既に未定義の動作があります。

修正するには、以下を動的に割り当てますstd::string

return boost::make_shared<std::string>(stream.str());

または、より単純に、std::string代わりにインスタンスを返して保存するだけです。

return stream.str();

コンパイラは戻り値の最適化を使用できるはずです。


c++11 ではスマート ポインターが導入されていることに注意してstd::shared_ptrください。

于 2013-05-13T14:28:37.567 に答える