高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先

spacer image


Technote 1082

The Problem with & (Simple) Fix to Purgeable WDEFs


内容

問題の定義

問題発生のシナリオ

なぜ今まで問題にならなかったのか

シンプルな解決法

その他の注意とコメント

まとめ
のテクノートでは、パージャブル(purgeable、パージ可能)なWDEFに起因する問題と、WDEFリソースをノン・パージャブル(non-purgeable、パージ不可)にすることによる解決法について説明します。
このノートは、WDEFリソースをその中に含むアプリケーションを開発しているデベロッパーと、WDEFコードリソースそのものを開発しているデベロッパーを対象としています。


問題の定義

他の定義関数と同様に、WDEFも実行時にメモリ中にロックしなければならないコードを含んでいます。もしアプリケーションがパージャブルなカスタムWDEFを使用していると、Memory Managerはアプリケーションヒープ上にメモリを確保する際にWDEFをパージする可能性があります。Window ManagerはWDEFをコールする前に、もし必要であればWDEFリソースを再ロードするでしょう。もし当該アプリケーションがフォアグラウンド・プロセスであれば、つまり、実行中であり、かつ、再前面(frontmost)に移行する必要がないのであれば、Window ManagerはWDEFリソースを再ロードすることができます。すべてはまったく問題なく動作します。
しかし、当該アプリケーションがフォアグラウンド・プロセスでなく、かつ、WDEFがパージされた場合、問題が発生します。

問題発生のシナリオ

この問題の原因となる事象を、順を追って述べます。 Window Managerは、アプリケーションがフォアグラウンド・プロセスでない場合でも、ウィンドウの再描画が必要なときにはWDEFをコールします。これは、当該アプリケーションのウィンドウのアップデートが必要になった場合(whenever your windows get erased)にWDEFを直接コールすることにより行われます。もしそのWDEFがパージされていると、Window ManagerはWDEFの再ロードを試みるでしょう。
しかし、当該アプリケーションはカレント・プロセス("current" application)ではないので、アプリケーションのコンテキストはリストアされておらず、また、当該アプリケーションのリソースチェインもカレント・プロセスのリソースチェインとは異なります。その結果、Window ManagerはWDEFを異なるリソースチェインからロードしようとします。 しかし、WDEFを探し出すことができずにSysError(87)をコールします。

なぜ今まで問題にならなかったのか

この問題がいままで顕在化しなかった原因は、以下の3つです。

  1. ほとんどのアプリケーションは、フローティングウィンドウを実装するためにWDEFを使用しています。Appleのヒューマン・インタフェース・ガイドライン(Human Interface Guidelines、HIG)で定められているとおり、アプリケーションはサスペンドされる前にフローティングウィンドウを隠さなければなりません。その場合、WDEFを使用したウィンドウは画面に表示されない(invisible)ので、もしWDEFがパージされていたとしてもWindow Managerはほとんどの場合WDEFの再ロードを行おうとしませんでした。
  2. バックグラウンド・アプリケーションは通常メモリをそんなに多く確保しないものなので、この問題を誘発しなかったものと思われます。そのような場合、たとえWDEFがパージャブルであったとしても、実際にはMemory ManagerはWDEFをパージしないでしょう。
  3. 大半のアプリケーションはメモリパーティションに余裕がない状態(with very tight memory partitions)で実行されることがないので、WDEFリソースがパージャブルであったとしてもパージする必要がありません。

シンプルな解決法

WDEFが再ロードされないという問題を解決する簡単な方法は、当該WDEFをノン・パージャブルにすることです。そうすることによりWDEFはMemory Managerによりパージされなくなるので、アプリケーションがフォアグラウンドにない場合でもWDEFが実行可能になるのです。

その他の注意とコメント

パージャブルなWDEFに関連する問題を考える場合に非常に重要な項目を以下に示します。
  • WDEF以外の定義関数(CDEFやMDEF等)はそれらを使用しているアプリケーションがカレント・プロセスでない場合にはコールされないので、この現象は発生しません。それらのタイプのリソースは、パージャブルのままで問題ありません。
  • "System"ファイル中(あるいはEnablerや、たとえばAaron等のシステム機能拡張ファイル中)のWDEFは、パージャブルのままで問題ありません。というのも、それらのファイル中に格納されているWDEFはいつでもリソースチェインに組み込まれているからです。これは、その時点でどのアプリケーションがカレントプロセスになっているかということにまったく影響を受けません。
  • パージャブルなWDEFを使用しているアプリケーションの中には、そのWDEFをメモリにロードした後にノン・パージャブルに変更するものがあります。その場合、この問題は発生しません。
  • サードパーティ製のユーティリティの中には、パージの発生をより頻繁に強制するものがあります。そのような場合、現象はさらに悪化します。
  • もしデータを内包しているWDEFに対してパージ・再ロードが行われると、そのデータの値はWDEFがディスク上に格納されていた状態に戻ります。ポピュラーな開発ツールの多くは、グローバル変数をそのコードリソースの中に埋め込みます(もし、当該WDEFがSetUpA4をコールする必要があるなら、そのような開発システムが使用されているのです)。WDEFが使用しているグローバル変数の値が突然まったく予想もしない値に変わってしまうとしたら、それはクラッシュの原因となり得ます。
  • 一般的には、アプリケーションはWDEFリソースをそのリソースマップからデタッチ(detach)すべきではありません(Technical Q & A TB - 575参照)。しかしながら、デタッチされたWDEFは、それがパージャブルであったとしてもディスクから再ロードされないということを知っておくことは重要でしょう。

まとめ

パージャブルなWDEFにより発生するこの問題は、それらのリソースをノン・パージャブルとすることにより解決可能です。

参考資料
Technical Q & A - TB 575
spacer image