1

私は共有ポインターが初めてで、共有ポインターがメンバー変数でもある場合、共有ポインターを初期化する方法を知りたいと思っていましたか?

現在、私のコードは次のようになっています: ヘッダー ファイルには、次のものがあります。

class Parser {
   public:
      Parser();
      ~Parser();

      boost::shared_ptr<XercesDOMParser> parser;
{

コンストラクターには、次のようなものがあります。

Parser::Parser() 
{
   try {
      XMLPlatformUtils::Initialize(); 
   } catch (...) {}

   parser = shared_ptr<XercesDOMParser> (new XercesDomParser()); 
}

私が持っているデストラクタで:

Parser::~Parser() {
   try {
      XMLPlatformUtils::Terminate();
   }catch(...) {}
}

ただし、Valgrind を使用してプログラムをコンパイルすると、次のエラーが表示されます。純粋な仮想メソッドが呼び出されました。アクティブな例外なしで終了しました。サイズ 8 の無効な読み取り。

初期化で間違っている可能性があることについての洞察はありますか?

私の疑いは、割り当てられていないメモリから読み取っていることです。

編集:

そのため、デストラクタで、終了コマンドの前に次のコード行を追加すると、メモリ リークとエラーがすべて消えました。

if (パーサー) parser.reset();

割り当てを解除する前に、パーサーへのすべての参照を削除する必要があるのはなぜですか?

ありがとうございます。

4

1 に答える 1

2

XercesDomParser のデストラクタを呼び出す前に、XMLPlatformUtils::Terminate() を呼び出しています。メンバー変数のデストラクタは、デストラクタ本体の実行後に呼び出されます。メンバ変数は宣言順に構築され、逆に破棄されます。

次のようなことができます。

class Parser : boost::noncopyable {
    struct XmlHandle {
        XmlHandle() { XMLPlatformUtils::Initialize(); }
        ~XmlHandle() { XMLPlatformUtils::Terminate(); }
    };

    XmlHandle m_handle;
    boost::shared_ptr<XercesDOMParser> m_parser;

public:
    Parser() : m_parser(new XercesDomParser) { }
};

そして、デフォルトのデストラクタを使用してください。コピー コンストラクターと代入演算子が必要な場合は、それに対処する必要があります。

ああ、例外をキャッチして捨てるのはおそらく悪い考えです...

于 2011-01-11T00:31:04.280 に答える