グローバルオブジェクトの破棄順

| コメント(0) | トラックバック(0)
拙作のウィンドウクラスに細工をしたらハマったというお話です。

きっかけはプロパティリスト(SetProp等のあれ)が遅い、と小耳に挟んだことでした。大したウィンドウを作るわけでもありませんが、更新頻度が異様に高いアプリは作ることがあるので、別の方法を試してみようとしたのです。

プロパティリストにはthisポインタを入れておき、メンバ関数でメッセージを処理するというお馴染みの使い方ですが、代わりといってもWTLみたいな頭おかしい実装は技量が及ばないので、静的std::mapにしました。

# 旧BorlandのVCLもWTLと同じ方法だったようですね

これを使って、PnPメッセージを処理するためダミーウィンドウを別スレッド上に実装した、ハードウェアを操作するクラスを書きました。

動作の確認としてコンソールアプリでグローバルに定義し、mainを抜けると...手元ではウィンドウクラスのオブジェクトよりstd::mapオブジェクトが先に破棄され、ウィンドウプロシージャ内でアクセス違反が発生してしまいました。

グローバルのオブジェクトは生成・破棄の順が規格上は未定義で、例えば何かのクラスに従属させるような制御方法もないとのこと。ちなみにマイクロソフトの場合、コンパイル時の出現順に生成し、破棄はその反対順だそうな。

「グローバル」というより静的な(staticに限らず)オブジェクトの寿命をコンパイラが区別できないという話らしく、静的メンバにしても意味はありません。

手っ取り早い回避法は、
  1. プロパティリストに戻す
  2. 後始末関数で明示的にDestroyWindowできるようにする
  3. グローバルで定義せず、他の関数からはポインタ経由とする
といったところでしょうか。

ちゃんとやれば自然と3.になりますが、2.が無難なところでしょうか。デストラクタからも後始末関数を呼んでおけば(始末済みチェックの上で)、3.では明示的に呼ばずに済みます。

トラックバック(0)

トラックバックURL: http://mychro.mydns.jp/cgi-bin/mt/mt-tb.cgi/311

コメントする

アーカイブ

ウェブページ

Powered by Movable Type 5.2.13

ホームページ