OLE パッケージ オブジェクトを含むドキュメントを開くと GDI オブジェクトが増加する
こんにちは、Visual Studio サポート チームです。
今回は、OLE パッケージ オブジェクトをプログラムから利用した場合に発生する問題についてご案内します。
現象
アプリケーションから OLE パッケージ オブジェクト (*1) を含むドキュメントを開いて閉じる操作を繰り返すと、アプリケーションの GDI オブジェクトの使用量が増加します。
増加量は僅かであるため、ほとんどのアプリケーションではこの問題が影響することはありませんが、パッケージ オブジェクトを含むドキュメントを、開いて閉じる動作を繰り返すようなアプリケーションでは、GDI オブジェクトの総量がプロセスごとに割り当てられた上限 (既定で 10,000) に達し、それ以降の GDI オブジェクトの生成に失敗して描画処理に問題が生じる場合があります。
(*1) パッケージ オブジェクトは、他のファイルやプログラムなどを OLE オブジェクトとしてドキュメントに挿入できるようにするためのオブジェクトです。
パッケージ オブジェクトの挿入
原因
本現象は、OLE パッケージ オブジェクトを管理する Windows OS のパッケージ管理コンポーネント (packager.dll) の不具合に起因するものです。
本コンポーネントでは、パッケージ オブジェクトごとにタイトルを表示するためのフォント オブジェクトを生成しますが、ドキュメントを閉じてもこのフォント オブジェクトが解放されないため、ドキュメントを開いて閉じる操作を繰り返すとフォント オブジェクト (GDI オブジェクト) が増加し続ける結果となります。
対応状況
マイクロソフトでは米国本社の開発部門でも本不具合を確認していますが、現時点では修正プログラムなどは提供されておらず、提供の予定はありません。
パッケージ オブジェクトは OLE 1.0 で導入されましたが、本不具合に起因する問題の報告がこれまでなかったことや、修正を行った場合の影響範囲の大きさなどを考慮して、修正が見送られている状況です。
ご利用のお客様にはご不便をおかけいたしまことお詫び申し上げます。
対処策
前述のとおり、GDI オブジェクトの増加量は僅かであるため、ほとんどのアプリケーションでは特別な対応は必要ありません。
プロセスを再起動せずに、パッケージ オブジェクトを含むドキュメントを頻繁に開いて閉じるようなアプリケーションでは、対策が必要となる場合があります。
ここで、パッケージ管理コンポーネントが内部で使用しているものであることから、アプリケーション側からこれを解放することはできず、本不具合による GDI オブジェクトの増加を抑止することはできません。このため、GDI オブジェクトの総数が、プロセスに割り当てられている GDI オブジェクト数の上限値 (既定値 10,000) に達する前の段階で、プロセスを安全に再起動させたり、ユーザーにアプリケーションの再起動を促すような対応をご検討ください。
参考情報
プロセスが使用している GDI オブジェクトの数は、GetGuiResources 関数を使用して取得可能です。GetGuiResources 関数の詳細については以下のドキュメントをご参照ください。
GetGuiResources function
(英語原文) https://msdn.microsoft.com/en-us/library/windows/desktop/ms683192(v=vs.85).aspx
(日本語訳) https://msdn.microsoft.com/ja-jp/library/cc429120.aspx
また、プロセスごとに割り当て可能な GDI オブジェクトの数の上限は既定で 10,000 となっています。GDI オブジェクトの上限に関しては、以下のドキュメントをご参照ください。
Windows の限界に挑む: USER オブジェクトと GDI オブジェクト – 第 2 部
https://technet.microsoft.com/ja-jp/windows/mark_17.aspx