Skip to content

std::shared_ptr<>仮実装中に問題発生 #18

@yossi-tahara

Description

@yossi-tahara

単純に回復すれば良いと思っていたのですが、複数回保存して回復した時、参照カウンタが回復できません。
boostのshared_ptrのシリアライズ・コードを確認したところ、この問題に対策されてました。
シリアライズしたshared_ptrをシリアライズする際、shared_ptrの追跡テーブルをstd::mapにて別途管理してました。firstはオブジェクトのアドレス、secondはshared_ptr自身です。
しかし、実装は意外に複雑です。

  1. 2番目以降の基底クラスへのポインタと派生クラス・オブジェクトのポインタはアドレスが一致しません。
    なので、shared_ptr追跡テーブルへは派生クラス・オブジェクトのアドレスを登録しています。

  2. 更に回復処理時、aliasingコンストラクタを使っています
    これは、元のshared_ptrと参照カウンタ、および、デリート処理(デリート先オブジェクトとデリータ)を共有しているがポイント先を自由に選択できるshared_ptrのコントラクタです。ポイント先の寿命が元の寿命以上の場合に使えます。

なぜ、aliasingコンストラクタを使っているのか非常に不思議だったのですが、この対策は近藤貴俊氏が行っていて丁寧に解説されていました。
簡単に説明すると、派生クラスへのポインタを管理しているshared_ptrと、それと同じインスンタスを2番目以降の基底クラスへのポインタで管理しているshart_ptrの2つを保存し、回復した時に不具合が出るのです。

shared_ptr追跡テーブルはshared_ptr<派生クラスの型>を使うことも可能な筈ですが、boostはstd::shared_ptr<void>型で管理しています。
そのため、std::mapに登録されているshared_ptrを単純に返却すると、基底クラスへのポインタに派生クラスのアドレスが設定され、ずれてしまいます。
この問題を回避するために、aliasingコンストラクタをうまいこと使っていました。(これを使わないと複雑なことになりそうです。)

この2点の対処を実装する予定です。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions