title.png

^<< 2011.05/1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 >>$

Trackback の仕組みはありませんので、コメントにでも残していただくと嬉しいかも、です。

(2011.05.07)

C++でインターフェースを提供するときに気をつけること

最近、コンストラクタがどうの、っていう話をいくつか読んで思いだしたのでメモがてら。

一年くらい前の話。 仕事で作っているアプリのメモリリークがどうしてもなくせない。 いろいろ調べて、最終的には使っていたとあるライブラリが原因だと分かりました。

このライブラリのインターフェースはC++で提供されています。 ある時間がかかる処理をさせるのに、非同期呼び出しと引数として通知用コールバックの為のインスタンスを渡す、 というよくあるパターン。こんな感じ。

class Hoge {
public:
      ・
      ・
      ・
    // 処理Fooをスタートさせる
    // 進捗や完了通知は progress に対して行われる
    virtual bool StartFoo(IProgressReceiver* receiver);
      ・
      ・
      ・
};

で、この IProgressReceiver を継承して実装したクラスを自分で作るんですが。。。 ライブラリ提供元が用意した IProgressReceiver はこんなんでした。

class IProgressReceiver {
public:
    virtual void ProgressReport(const ProgressContext& context) = 0;
};

はい、もうおわかりのとおり仮装デストラクタ仮想デストラクタがありません。 C++には Java の interfaceキーワードみたいなものはない(VC++独自拡張にはあるけど)ので、 正しくはこうしないと、継承先のクラスのデストラクタが正しく呼ばれずリークします。

class IProgressReceiver {
public:
    virtual ~IProgressReceiver() {}
    virtual void ProgressReport(const ProgressContext& context);
};

このときは、ライブラリ提供元にお願いして修正してもらうことができたので事なきを得ました。

逆に、自分でもこういうI/Fを提供することはあるので気をつけないと。

ツッコミ