メモリが解放されない?

Anonymous
2013-10-15T16:34:20+00:00

Windows 8に固有の問題かどうかは分かりませんが、教えてください。

基本的にスリープや休止状態を使いシャットダウンはなるべくしないようにして使っているのですが、そうやって何日も使っているとアプリケーションが起動できなくなったり、起動してもダイアログやメニュが正しく表示されなくなったりして困っています。

そういうときにタスクマネージャで見てみると、メモリタブのメモリのコミット済みが異常に大きい値になっています。メモリが足りなくなっているのが、アプリケーションが起動できなくなっている理由ではないかと考えています。Windowsを再起動した直後は、こんなにコミット済みメモリは多くないです。せいぜい2.xGBか3.xGB程度なのですが、数日経過するとウィンドウアプリをすべて閉じてもコミット済みは7.4/8.6GBとかになっています。

もう少し調べてみると、どうも taskhostex.exe と explorer.exeの2つのプロセスがかなりのメモリを「コミット済み」にしていることが分かりました。試しにtaskhostex.exeをタスクマネージャから強制終了するとコミット済みメモリが2~3GBほど、explorerを強制終了すると1~1.5GBほど減ります。これらのプロセスが、メモリを大量に消費しているか、もしかしてメモリを解放しないままになっているのでしょうか?強制終了ではなく、これらのプロセスが使用するメモリ量を制限するか、安全に解放させる方法はありませんか?

また、ProcessExplorerを使用してtaskhostex.exeが提供しているタスクを調べてみると、Microsoft PlaySoundService Class/MsCtfMonitor Task handler/Wininet Cache task objectの3つの機能を提供しているようですが、このいずれかに問題があるのでしょうか?

ちなみにWindows ストアアプリは、まったく使用していません。使っているのは普通のデスクトップアプリばかりです。

この現象はメーカの違う2つのPCで確認しているので、固有の問題というわけではないと考えています。何か原因をご存知でしたら、教えていただきたいと思います。

よろしくお願いします。

(追記)

2台のPCで確認していますが、一方はWindows 8 64bitで、もう一方はWindows 8 Pro 64bitです。

搭載メモリはどちらも8GBです。

よろしくお願いします。

家庭向け Windows | 以前の Windows バージョン | パフォーマンスとシステムの失敗

ロックされた質問。 この質問は、Microsoft サポート コミュニティから移行されました。 役に立つかどうかに投票することはできますが、コメントの追加、質問への返信やフォローはできません。

0 件のコメント コメントはありません

61 件の回答

並べ替え方法: 新しい順
  1. Anonymous
    2015-02-09T12:41:53+00:00

    ご意見ありがとうございます。

    > VirtualAlloc() API が提供する機能をちゃんと理解できていますか?

    > (というか、「仮想メモリ」と「物理メモリ」の区別がちゃんとできていますか?)

    「仮想メモリ」「物理メモリ」は区別できていると思いますが、考えてみると「コミット済みメモリ」の定義についてはまだ理解が少し曖昧なきがします。

    >>  「呼び出し側プロセスの仮想アドレス空間内のページ領域を、予約またはコミットします。」

    > つまり、この API を呼び出したところで、物理メモリにはなんら影響を与えない。。。ということではないでしょうか?

    この点(と私が書いたというテストプログラムの件)については、謝らなければなりません。

    VirtualAllocではMEM_RESERVE|MEM_COMMITフラグを渡している、という情報が抜けていました。

    このフラグを設定しているので、VirtualAllocで与えられたメモリにはアクセスが可能となっています。実際、書き込みができることを確認したプログラムでした。

    それから、私の理解ではMEM_COMMITを渡しているということは、具体的に物理メモリがマッピングされたか、あるいは、ページファイル上にアクセスできるメモリ領域が確保されたことだと理解しています。間違いないですよね?

    > VirtualAlloc() API でコミットした「仮想メモリ上の領域」が「物理メモリ」上にマップされるのは、基本的に VirtualLock() - VirtualUnlock() の間だけのはずです。

    いやVirtualLock()~VirtualUnlock()間は、そのメモリ範囲がページファイルにスワップされないことが保証されるということだったはず。

    MEM_COMMITフラグを伴ってVirtualAllocすれば、そのメモリにはアクセスできるが、その段階で物理メモリにあるかページファイルにあるかはOS次第で、ページファイルにあるときにアクセスすればページフォールトが発生して、OSが読みだして物理アドレスを与えてくれる、という動作のはずです。

    それから、全部のレスを読まれていないので仕方がありませんが、このスレで私は一度も物理メモリ(アドレス)の議論をしてきたことはありません。あくまでも、タスクマネージャ上での「使用中」と「コミット済み」のメモリ量の関係を議論してきました。

    **>**提示されているサイトは、特定のプロセスにおける「仮想アドレス空間」のメモリ マップ状態を調べる方法だと思います。(ちゃんと読んでないけど。)

    今は、explorer.exeとtaskhostexe.exeのメモリの使い方が怪しいと疑っている段階なので、むしろプロセス単位でのメモリの内容が分かるほうがありがたいのです。ここでも物理アドレスは全然気にしていなくて、仮想アドレス空間上でどのようにメモリを使っているかがわかると、そのうち何MByteが「使用中」メモリで、何MByteが「コミット済み」メモリなのかが調べられると思って、注目しているところです。

    > WinDBG はソフトウェア開発者ですら敬遠する解析ツールですが、もし挑戦する根性があるのでしたら、ぜひ頑張ってください。

    WinDBGは最近は使っていませんが、10年くらい前まではドライバの開発でデバッグで大変お世話になりました(当時はRS232C接続のリモートデバッグで非常に苦労した思い出が・・・)。

    コマンドベースなので、まだまだすべての機能を使いこなせているとは思えませんが、ダンプファイルから解析するという方法は考えつかなかったので検討してみたいと思います。ありがとうございました。

    > 個人的には、本スレッドはこのコミュニティで扱う範疇を超えているような気がしています。

    そのとおりだと思います。

    最初は、同じような人がいて解決策がサクッと分かったらいいな、くらいの軽い気持ちでした。あるいは、MSがホストのフォーラムですから、モデレータの方が我々の知らない情報に通じていて、いいアドバイスをくれるのではないかとも期待していました。

    しかし、モデレータとはもったいぶった言い方で、moderate(穏やか)という言葉から察するに、結局は某掲示板のように炎上しないように監視しているだけに過ぎないのかも知れませんね。そういう意味でもこのフォーラムでのこの質問はもう不適切でしょうね。

    この回答は役に立ちましたか?

    0 件のコメント コメントはありません
  2. Anonymous
    2015-02-09T12:11:54+00:00

    気分を害したのであれば、お詫びします。

    もしそうであれば、もうお返事はいただけないと思いますが、もし少しでもお助けいただける気持ちがおありでしたら、もう少しお付き合い願えませんか?

    > そりゃ休止状態を使えば使うほどコミットメモリは増加する思う、既知の常識。

    すみません。これが常識だということは初めて聞きました。「常識」=「説明するまでもない」ということかもしれませんが、常識であればどこか他でもそういう書き込みなり情報があるはずだと思います。どこか一つでもよいので例示していただけませんか?

    私がこのスレで議論したいのは、「休止状態を使うからコミットメモリが増える」ということではなく、「例えば一日連続してPCを使い続けるだけでコミットメモリが増えてしまう。アプリを閉じても『使用中』と『コミット済み』がかけ離れた数値になってしまう。それはなぜか?」ということです。

    そして、調査する中で気がついたのはexplorer.exeとtaskhostex.exが大量のメモリを「コミット済み」にしてしまっているというところまでわかったので、今はそこの部分を調べたいということです。

    > シャットダウンとスリープの何れかで開放になる、これ位は知って置いてください常識だから。

    これも初耳です。

    シャットダウンでメモリが開放されるのは当たり前としても、スリープで解放されるというのはにわかに信じがたいです。

    その情報のソースがあれば教えて下さいませんか?それか、「解放される」のが何かを明示されていませんけど、貴方の環境で確認できる具体的な数値(スリープ前後で何がどのくらい開放されるのか?)を教えて下さい。こちらの環境でも同じようにやってみて、どうなるのか知りたいです。

    よろしくお願いいたします。

    この回答は役に立ちましたか?

    0 件のコメント コメントはありません
  3. 削除済み

    この回答は当社の行動規範に違反したため削除されました。 アクションを実行する前にこの回答を手動で報告したか、自動検出機能により特定しました。 詳細については、当社の行動規範を参照してください。


    コメントはオフになっています。 詳細情報

  4. 削除済み

    この回答は当社の行動規範に違反したため削除されました。 アクションを実行する前にこの回答を手動で報告したか、自動検出機能により特定しました。 詳細については、当社の行動規範を参照してください。


    コメントはオフになっています。 詳細情報

  5. Anonymous
    2015-02-06T13:18:09+00:00

    まだ解決してませんが、追加で判明したことがあるので報告まで。

    VMMapというツールを使えば、プロセスがどのようにメモリを使っているかがより詳細に見えることが分かりました。

    このツールによると、"unusable"なるメモリが大量に確保されたままになっていると分かりました。この"unusable"が増える現象は、explorer.exeとtaskhostex.exeで特に顕著に起きています。

    下の画像は、コミット済みメモリが増えた時にexplorer.exeのメモリ使用状況をVMMapで確認したところですが、この"unusable"メモリが2GByteにもなっていました。他のプロセスでこんなに大きくなっているものありません。多くても数十MByte程度です。

    この画像では、explorerは3.3GByteほどのコミット済みメモリを持っているようですが、この状態explorerを殺すと、タスクマネージャ上の表示は7.0GByte→4.0GByteに下がりました。DLLなどのファイルの一部はファイルマッピングで他のプロセスと共有していることを考えると、3.0GByteの減少はおよそ妥当な線ではないかと考えてます。

    比較しやすいように、問題が発生するまえに取っておいた画面キャプチャを右隣りに貼り付けてあります。

    問題発生前から特に増えているのが、"unusable"ですが、"Shareable"も結構増えています。が、それでも300MByte程度です。

    この"unusable"というメモリは何なんでしょうか。調べたところでは、VirtualAllocで割り当てたページの残骸のようです。VirtualAllocは64KByte単位でメモリを割り当てますが、小さい量のメモリ(4Kとか8Kbyte)をこのVirtualAllocで割り当てると、残りの60~56KByteは使用できないままになってしまうようです。それが蓄積して、このときは2GByteにもなっているものと思われます。

    疑問点は、

    • どのモジュールがこの小さいメモリ領域をVirtualAlloc APIで割り当てているのか?なぜ、ランタイムのヒープではなくて、VirtualAllocを使ったのか?
    • 割り当てたメモリは解放されないのか?ずっと使っているのか?それとも解放するのを忘れているのか?

    の2点です。

    試しに、簡単なテストプログラムを作って小さいメモリをVirtualAllocし続けるようにしてみると、確かに上のVMMapが示すような"unusable"が何GByteにもなるようなプロセスとなりました。しかし、タスクマネージャ上の”コミット済み"は何GByteも増えなかったです。この点では、explorer.exeの振る舞いとは異なっています。なぜかはまだ分かりません。

    上の説明が正しいとすると、"unusable"と表示されているメモリ領域にはそのVirtualAlloc API呼び出す理由となったメモリ領域がペアで存在するはずです。ざっと調べる限り、そのペアとなっているメモリはほとんどがShareableなメモリで、サイズは4Kか8Kでした。また、比較的若いアドレス0x00010000あたりから連続してShareable+unusableなメモリ領域が連続していることから、これらのメモリはexplorer.exe自体が割り当てて使用しているのではないか?と推測しています。explorer.exeがロードしたDLLやシェルエクステンションではなく、やはりexplorer.exe自体が怪しいのでは?という予測です。

    こちらのページ(http://blogs.microsoft.co.il/sasha/2014/07/22/tracking-unusable-virtual-memory-vmmap/)に、WinDbgを使ってVirtualAlloc系API呼び出しをトラップする方法が記されているので、後日時間があるときに試してみたいと思います。VirtualAllocにブレークポイントを張って、スタックトレースすればどのモジュールから呼び出されているかがある程度分かるはずです。この方法で犯人を絞り込んでみたいです。

    この回答は役に立ちましたか?

    1 人がこの回答が役に立ったと思いました。
    0 件のコメント コメントはありません