Microsoft が 2026年6月26日に公開した「The case of the DLL that was not present in memory despite not being formally unloaded, part 2」は、新機能の追加や設定変更の告知ではなく、Windows アプリケーションのクラッシュ解析に関する技術記事です。結論から言うと、管理者がすぐに変更すべき Microsoft 365 や Azure の設定、移行期限、グローバル展開スケジュールは示されていません。
ただし、Windows 上で動作する業務アプリ、常駐アプリ、C++ 製アプリ、DLL を明示的に読み込むアプリを運用している組織にとっては重要です。今回の記事は、「正式にアンロードされていないはずの DLL がメモリ上に存在しない」という一見不可解なクラッシュが、実はメモリ破損によって別の形で表面化した可能性を示しています。特に、アプリ終了時のクラッシュを「利用者影響が小さい」と見過ごしている場合は、ログ収集やクラッシュダンプの確認方針を見直す価値があります。(Microsoft for Developers)
Microsoft の「The case of the DLL that was not present in memory despite not being formally unloaded, part 2」で確認すべきポイント
今回の Microsoft 公式情報は、The Old New Thing に掲載された Raymond Chen 氏の記事です。主題は「Tying two bugs together」、つまり別々に見えていたクラッシュ事象を、同じ根本原因に結び付けて考えるというものです。
記事で扱われているのは、次のような現象です。
あるプロセスで、DLL が正式にはアンロードされていないように見えるにもかかわらず、実際にはメモリからマップ解除されており、その DLL 内のコードを呼び出そうとしてクラッシュする。さらに別のクラッシュでは、データ構造の一部に 01 という 1 バイトが書き込まれて破損している。Microsoft の記事では、この 2つの現象が同じメモリ破損バグの別表現だった可能性を説明しています。(Microsoft for Developers)
重要なのは、これは Windows の一般利用者向けの更新通知ではなく、開発者・運用担当者向けの障害解析ノートに近い内容だという点です。したがって「どの設定を有効化すればよいか」ではなく、「自社アプリやサードパーティ製アプリで似たクラッシュが起きたときに、どこを疑うべきか」を読み取る記事です。
今回の更新は新機能ではなく、DLL とメモリ破損の解析記事
今回の公式記事から読み取れる更新ポイントを、実務目線で整理すると次の通りです。
| 項目 | 内容 |
|---|---|
| 公開日 | 2026年6月26日 |
| 対象 | Windows アプリケーション開発者、デスクトップアプリ運用担当者、障害解析担当者 |
| 主なテーマ | DLL が正式にアンロードされていないように見えるのに、実際にはメモリ上から消えているクラッシュの解析 |
| 直接の製品変更 | 記事内では確認されていない |
| 管理センターの設定変更 | 記事内では示されていない |
| 移行期限 | 記事内では示されていない |
| 管理者が見るべき点 | アプリ終了時クラッシュ、メモリ破損、DLL のロード・アンロード処理、サードパーティ製アプリの安定性 |
Microsoft 365 管理センター、Azure ポータル、Intune、Defender、Entra ID などで何かを設定変更するタイプの情報ではありません。むしろ、Windows 上で業務アプリを運用する組織が、クラッシュ調査やベンダー問い合わせの際に参照すべき技術的なヒントと捉えるのが適切です。
何が起きていたのか:正式にアンロードされていない DLL が消える仕組み
今回の記事の中心は、HMODULE の下位ビットと、LOAD_LIBRARY_AS_DATAFILE による DLL の扱いです。
Microsoft Learn によると、LoadLibraryEx は DLL を通常の実行可能モジュールとして読み込むだけでなく、リソース取得などを目的として「データファイル」として読み込むことができます。LOAD_LIBRARY_AS_DATAFILE などで読み込まれた場合、DLL は通常の実行用 DLL とは異なる扱いになり、関数呼び出しの対象として使う前提ではありません。(Microsoft Learn)
今回の記事では、どこかの処理が本来書き込んではいけない場所に 01 という 1 バイトを書き込んでいたことが手掛かりになっています。HMODULE の下位ビットは、データファイルとして読み込まれたモジュールを識別するために使われます。もし既存の HMODULE の下位バイトが誤って 01 に書き換わると、本来は通常の DLL ハンドルだったものが、データファイル用のハンドルのように見えてしまいます。(Microsoft for Developers)
その状態でプロセス終了時のクリーンアップ処理が FreeLibrary を呼び出すと、システム側は「これはデータファイルとして読み込まれたモジュールだ」と解釈し、通常の DLL アンロードとは異なる処理でメモリマッピングを解除します。結果として、DLL の管理リスト上では存在しているように見えるのに、実際のメモリ上には存在しないという矛盾した状態が生まれます。(Microsoft for Developers)
通常の DLL とデータファイルとして読み込まれた DLL の違い
障害調査で混乱しやすいポイントは、「DLL が読み込まれている」という言葉が常に同じ意味ではないことです。
| 読み込み方 | 主な目的 | 典型的な用途 | 注意点 |
|---|---|---|---|
| 通常の DLL として読み込み | コード実行 | 関数呼び出し、プラグイン読み込み | 参照カウントや DllMain の動作を意識する必要がある |
| データファイルとして読み込み | リソース参照 | メッセージ、アイコン、文字列リソースの取得 | 実行用 DLL として扱えないケースがある |
| イメージリソースとして読み込み | PE 形式のリソース参照 | リソース取得の最適化 | 通常の DLL ロードとは管理方法が異なる |
Microsoft Learn では、LOAD_LIBRARY_AS_DATAFILE を使用した場合、ファイルはデータファイルのように仮想アドレス空間へマップされ、実行準備は行われないと説明されています。また、この方法で読み込まれた DLL は GetProcAddress などの通常の関数解決用途には使えません。(Microsoft Learn)
この違いを理解していないと、クラッシュダンプ上で「DLL はロード済みのはずなのに、なぜコードが存在しないのか」という誤った方向に調査が進みやすくなります。
影響範囲:Microsoft クラウド設定ではなく Windows アプリ運用が中心
今回の情報の影響範囲は、Microsoft 365 や Azure のテナント全体に対する設定変更ではありません。対象になるのは、Windows 上で動くアプリケーションの設計、実装、運用監視です。
特に注意したいのは、次のような環境です。
| 対象 | 確認すべき理由 |
|---|---|
| C++ 製のデスクトップアプリ | LoadLibrary、LoadLibraryEx、FreeLibrary を直接扱っている可能性がある |
| プラグイン機構を持つ業務アプリ | DLL のロード・アンロード順序が複雑になりやすい |
| 常駐アプリ、エージェント、監視ツール | 長時間稼働後の終了処理で問題が表面化しやすい |
| サードパーティ製アプリを多数導入している端末 | 自社でコードを修正できず、ベンダー調査が必要になる |
| 終了時クラッシュを無視している運用 | ユーザー影響が小さく見えても、根本にメモリ破損がある可能性がある |
Microsoft の記事でも、問題がプロセス終了時に発生していたため、長く見過ごされていた可能性に触れています。アプリ終了時のクラッシュは、ユーザーが作業を終えた後に発生するため業務影響が目立ちにくい一方で、内部的には重大なメモリ破損を示している場合があります。(Microsoft for Developers)
設定変更と移行期限はあるのか
今回の公式情報では、管理者が実施すべき設定変更や移行期限は示されていません。ここは誤解しやすいので、明確に切り分ける必要があります。
| 確認項目 | 今回の扱い |
|---|---|
| Microsoft 365 管理センターでの設定変更 | なし |
| Azure 側の構成変更 | なし |
| Windows Update の適用期限 | 記事内では示されていない |
| API 廃止や移行期限 | 記事内では示されていない |
| 開発者向けの注意喚起 | あり |
| クラッシュ調査時の着眼点 | あり |
ただし、設定変更がないからといって、運用上の対応が不要という意味ではありません。自社で Windows アプリを開発している場合や、業務端末でクラッシュが増えている場合は、今回の記事を「調査観点の追加」として扱うべきです。
管理者が確認すべきポイント
管理者や運用担当者は、ソースコードの細部まで追わなくても、次の観点を押さえておくと実務で役立ちます。
アプリ終了時のクラッシュを軽視しない
アプリ終了時のクラッシュは、ユーザーから見ると「作業は終わっているから問題ない」と判断されがちです。しかし、終了処理では DLL、スレッド、ファイルハンドル、ログ出力、プラグイン解放などが一気に行われます。ここで発生するクラッシュは、単なる終了時の後始末ではなく、以前から存在していたメモリ破損が最後に表面化したものかもしれません。
実務では、次のように扱うとよいでしょう。
| 状況 | 推奨対応 |
|---|---|
| 特定アプリだけが終了時に落ちる | アプリ名、バージョン、発生端末、発生タイミングを記録する |
| 複数モジュールで似たクラッシュが出る | それぞれ別問題と決めつけず、共通するメモリ破損を疑う |
| ユーザー影響が少ないため放置している | ダンプ取得を有効化し、再現頻度と影響範囲を確認する |
| 更新後にクラッシュが増えた | OS 更新、アプリ更新、セキュリティ製品更新の時系列を整理する |
DLL のロード・アンロード処理を棚卸しする
自社開発アプリがある場合は、LoadLibrary、LoadLibraryEx、FreeLibrary、GetModuleHandle などを使っている箇所を確認します。特に、RAII で HMODULE を自動解放している場合、ハンドルの所有権が曖昧だと終了時に問題が出る可能性があります。
Microsoft Learn では、FreeLibrary は DLL の参照カウントを減らし、参照カウントがゼロになるとプロセスのアドレス空間からモジュールをアンロードすると説明されています。また、GetModuleHandle が返すハンドルは参照カウントを増やさないため、そのハンドルを FreeLibrary に渡すと DLL が早期にアンロードされる可能性があると注意されています。(Microsoft Learn)
確認時は、次のような観点でコードレビューすると効果的です。
| 確認ポイント | 悪い例 | 望ましい考え方 |
|---|---|---|
| ハンドルの所有権 | どこで取得した HMODULE か分からない | LoadLibrary で取得したものだけを解放対象にする |
GetModuleHandle の扱い | 取得したハンドルをそのまま FreeLibrary に渡す | 参照カウントを増やさないハンドルとして扱う |
| データファイル読み込み | リソース取得用のハンドルを実行用 DLL と同じように扱う | 用途ごとにハンドル管理を分ける |
| 終了処理 | グローバルデストラクタや終了時処理に任せきり | 明示的な終了順序を設計する |
サードパーティ製アプリはベンダーに「終了時クラッシュ」としてではなく「メモリ破損疑い」として伝える
今回の記事では、根本的なメモリ破損の原因は記事執筆時点で特定されていないとされています。また、現象が特定のプロセスでのみ発生し、複数モジュールにまたがって表面化していることから、そのプログラム自体、またはそのプロセス固有のシステム利用方法に問題がある可能性が示されています。(Microsoft for Developers)
このようなケースでは、ベンダーへの問い合わせ文面が重要です。
「アプリ終了時にたまに落ちます」だけでは、優先度が低く扱われる可能性があります。代わりに、次の情報を添えると調査が進みやすくなります。
| 添付・共有すべき情報 | 理由 |
|---|---|
| アプリ名と正確なバージョン | 既知不具合や修正済みバージョンと照合できる |
| Windows のバージョンと更新状況 | OS 依存の問題か切り分けやすい |
| クラッシュ発生時刻 | イベントログや監視ログと突合しやすい |
| クラッシュダンプ | スタックトレースや破損箇所を確認できる |
| 再現手順 | ベンダー側で検証しやすくなる |
| 複数端末での発生有無 | 環境依存か製品不具合かを判断しやすい |
問い合わせでは、「終了時クラッシュ」だけでなく、「DLL のアンロード処理またはメモリ破損の可能性がある」と明記すると、開発部門にエスカレーションされやすくなります。
開発チームが見直すべき実装ポイント
開発者向けには、今回の記事から学べる点が多くあります。特に C++ やネイティブコードを含むアプリでは、ハンドルの所有権とメモリ破損の検出を重点的に見直すべきです。
HMODULE を単なる整数のように扱わない
今回の事例では、HMODULE の下位ビットが意味を持つことが重要な手掛かりになっています。ポインタやハンドルを「実質的には数値」と見なして加工したり、構造体の境界を越えて書き込んだりすると、わずか 1 ビットの変化でもシステム API の解釈が変わります。
特に危険なのは、次のような実装です。
// 悪い例:所有権が不明な HMODULE を自動解放対象にしてしまう
HMODULE h = GetModuleHandleW(L"example.dll");
// この h を RAII ラッパーに入れてデストラクタで FreeLibrary するのは危険
GetModuleHandle は、指定されたモジュールのハンドルを取得しますが、参照カウントを増やしません。そのため、取得したハンドルを FreeLibrary に渡すべきではないと Microsoft Learn でも説明されています。(Microsoft Learn)
より安全な方針は、次のように「所有するハンドル」と「参照するだけのハンドル」を型や命名で分けることです。
// 所有するハンドル:LoadLibrary で取得し、最後に FreeLibrary する
HMODULE ownedModule = LoadLibraryW(L"example.dll");
// 参照するだけのハンドル:GetModuleHandle で取得し、FreeLibrary しない
HMODULE borrowedModule = GetModuleHandleW(L"example.dll");
メモリ破損は「最初に落ちた場所」が原因とは限らない
今回の Microsoft 記事で実務的に重要なのは、クラッシュ箇所と原因箇所が一致しない点です。DLL 呼び出し時にクラッシュしていても、原因はその DLL ではなく、もっと前に発生した 1 バイトの不正書き込みかもしれません。
調査時は、次の順序で確認すると切り分けやすくなります。
| 手順 | 確認内容 |
|---|---|
| 1 | クラッシュが発生した DLL や関数を確認する |
| 2 | その DLL が本当にメモリ上に存在するかを確認する |
| 3 | DLL のロード・アンロード履歴を確認する |
| 4 | HMODULE や管理構造体の破損がないかを見る |
| 5 | 同じプロセス内の他クラッシュと共通点を探す |
| 6 | AddressSanitizer、PageHeap、Application Verifier などで不正書き込みを検出する |
ポイントは、クラッシュ単位で個別に直そうとしないことです。Microsoft の記事でも、DLL がメモリから消えていたクラッシュは、「不適切な場所に 01 バイトを書き込む」という根本バグの別表現だったと説明されています。(Microsoft for Developers)
グローバル企業での運用上の注意点
グローバル環境では、同じアプリでも地域、言語、端末イメージ、セキュリティ製品、周辺デバイス、プラグイン構成が異なることがあります。そのため、クラッシュが一部地域だけで発生しても、単なるローカル問題と決めつけない方が安全です。
特に次のような切り口で情報を集めると、原因の絞り込みに役立ちます。
| 切り口 | 見るべきポイント |
|---|---|
| 地域 | 特定国・地域の端末だけで発生していないか |
| 言語環境 | IME、ロケール、表示言語、文字コード処理が関係していないか |
| 端末モデル | 特定メーカーや特定ドライバー構成に偏っていないか |
| セキュリティ製品 | EDR、DLP、暗号化、アプリ制御が DLL 読み込みに影響していないか |
| アプリ構成 | プラグイン、アドイン、拡張モジュールの差分がないか |
| 更新タイミング | Windows 更新、アプリ更新、ドライバー更新後に増えていないか |
グローバル向けに管理する場合、イベントログやクラッシュダンプの収集ルールを地域ごとにバラバラにせず、共通のフォーマットで集めることが重要です。たとえば、問い合わせテンプレートに「アプリ終了時か、操作中か」「クラッシュ直前に開いていたファイル」「接続していた周辺機器」「利用していたプラグイン」を含めるだけでも、後続調査の品質が大きく変わります。
よくある誤解と失敗しやすいポイント
今回の内容は低レイヤー寄りのため、運用現場では誤解が起きやすい分野です。特に次の点に注意してください。
| 誤解 | 正しい見方 |
|---|---|
| DLL がリストにあるならメモリにも存在する | 管理情報と実際のメモリ状態が食い違うケースがある |
| 終了時クラッシュは業務影響が小さい | 根本にメモリ破損がある場合、別のタイミングで重大化する可能性がある |
| 落ちた DLL が必ず悪い | その前に別モジュールがメモリを壊している可能性がある |
FreeLibrary はどの HMODULE に対しても安全 | ハンドルの取得方法と所有権を確認する必要がある |
| 設定変更で解決できる | 今回の記事は設定変更の案内ではなく、障害解析の考え方を示すもの |
特に FreeLibrary の扱いは注意が必要です。Microsoft Learn では、FreeLibrary はロード済み DLL の参照カウントを減らし、参照カウントがゼロになるとプロセスのアドレス空間からアンロードすると説明されています。つまり、誤ったハンドルや所有していないハンドルに対して呼び出すと、想定外のアンロードにつながる可能性があります。(Microsoft Learn)
企業の管理者が今すぐ実施すべき確認リスト
今回の Microsoft 公式情報を受けて、管理者が現実的に行うべきことは、設定変更ではなく「監視と調査の準備」です。
| 優先度 | 確認項目 | 具体的なアクション |
|---|---|---|
| 高 | 終了時クラッシュの有無 | イベントログ、クラッシュレポート、EDR のアプリクラッシュ検知を確認する |
| 高 | 影響アプリの特定 | 同じ実行ファイル、同じ DLL、同じバージョンに偏りがないか集計する |
| 高 | ベンダー問い合わせ準備 | バージョン、再現手順、ダンプ、発生端末情報をまとめる |
| 中 | 自社開発アプリの DLL 管理 | LoadLibrary / FreeLibrary / GetModuleHandle の利用箇所を棚卸しする |
| 中 | ダンプ取得設定 | 再現端末でクラッシュダンプを取得できるようにする |
| 中 | 更新履歴の整理 | OS、アプリ、セキュリティ製品、ドライバーの更新時系列を確認する |
| 低 | 利用者への案内 | 「終了時に落ちるだけ」でも報告対象にするよう周知する |
グローバル展開している企業では、まず一部地域や一部部門で発生している終了時クラッシュを集計し、同じプロセス名・同じ DLL・同じアプリバージョンに偏っていないかを見るのが現実的です。そこから、ベンダー問い合わせ、自社コードレビュー、端末構成差分の調査へ進めると無駄が少なくなります。
今回の情報をどう受け止めるべきか
「The case of the DLL that was not present in memory despite not being formally unloaded, part 2」は、Microsoft の新機能や仕様変更を知らせる記事ではありません。管理者が何かのスイッチを有効化したり、期限までに移行作業を行ったりする内容でもありません。
しかし、Windows アプリの安定運用という観点では重要です。特に、次の3点を押さえておくと実務に活かせます。
第一に、DLL が「正式にアンロードされていない」ように見えても、メモリ上の実態と一致しているとは限りません。第二に、1 バイトの不正書き込みでも、HMODULE のようなハンドルの意味を変えてしまうことがあります。第三に、アプリ終了時のクラッシュは、目立たないだけで重大なメモリ破損のサインである可能性があります。
管理者は、設定変更を探すよりも、まず自社環境で終了時クラッシュや特定アプリの不安定化が起きていないかを確認してください。開発チームは、DLL ハンドルの所有権、FreeLibrary の呼び出し条件、メモリ破損検出の仕組みを見直すことが次の一手です。

コメント