none
メモリとタスクの解放 RRS feed

  • 質問

  •  Visual Studio 2015C#とC++ネイティブで書かれたDLLに関することで質問があります。DLLはブラックボックスに近いです。

     C#でDLLの関数を呼ぼうと思っています。そして、DLLの関数の強制終了をしてメモリの解放をC#から命令して、実現したいと思っているのですが、どのような命令が必要ですか? また、参考のサイトがあれば、教えてください。


    2016年5月7日 14:16

回答

  • まず、中断の意味と動作の仕様を確定し、その方法と実効性を確認すべきかもしれません。
    意図した中断自体ができなければメモリの事など心配する必要がないからです。

    一般に、実行中のネイティブコードの関数を外部から中断する手段は、
    それを実行中のスレッドを停止/終了する以外にはないと思います。
    この場合、正しく実装されたスレッドであり、かつ中断を前提とした関数ならば
    メモリは正しく解放されることが期待できます。

    中断可能な機能を持つ関数を、それを知る他のコードから中断するのならば、
    その(ネイティブの)中断処理コードにおいて、関数自身の管理するメモリを
    開放する処理がコードされているべきで、そうでなければ事実上使えません(つまり瑕疵ですね)。
    ただし、本条件では仕様上の確認しかできないかもしれません(コードの検証が不能と判定しました)。

    独立したプロセス上で動作させているならば、プロセスごと削除できますが、
    期待した結果をもって関数が中断したかどうかは、対象の関数の実装によるため、
    本件では検証不可能と断定できそうです。

    • 回答としてマーク ちゅんた 2016年5月22日 4:40
    2016年5月7日 15:57

すべての返信

  • 基本的にそういうことはできません。

    FreeLibrary で DLL をアンロードすることはできるかもしれませんが、DLL が確保していたリソース・メモリを解放できるわけでもありません。
    よって、プロセス単位で終了する以外、DLL 外から無理矢理解放させることはできませんので、そういった道筋で考えを進めるのではなく、DLL を改修する・自作しなおす、あるいは強制終了・解放せずとも済む仕組みを目指すことを考えていただいた方が筋は良いと思います。

    逆に言えばプロセスを分ければやりたいことはできるということになります。
    どうしても、DLL が変更不可で、強制終了させる必要があるのであれば、その DLL を使うワーカープロセスを自作し、アプリケーションとの間でプロセス間通信で制御するといった少し難しいことを考えていただくことになると思います。
    2016年5月7日 15:08
    モデレータ
  • まず、中断の意味と動作の仕様を確定し、その方法と実効性を確認すべきかもしれません。
    意図した中断自体ができなければメモリの事など心配する必要がないからです。

    一般に、実行中のネイティブコードの関数を外部から中断する手段は、
    それを実行中のスレッドを停止/終了する以外にはないと思います。
    この場合、正しく実装されたスレッドであり、かつ中断を前提とした関数ならば
    メモリは正しく解放されることが期待できます。

    中断可能な機能を持つ関数を、それを知る他のコードから中断するのならば、
    その(ネイティブの)中断処理コードにおいて、関数自身の管理するメモリを
    開放する処理がコードされているべきで、そうでなければ事実上使えません(つまり瑕疵ですね)。
    ただし、本条件では仕様上の確認しかできないかもしれません(コードの検証が不能と判定しました)。

    独立したプロセス上で動作させているならば、プロセスごと削除できますが、
    期待した結果をもって関数が中断したかどうかは、対象の関数の実装によるため、
    本件では検証不可能と断定できそうです。

    • 回答としてマーク ちゅんた 2016年5月22日 4:40
    2016年5月7日 15:57
  • ワーカープロセスやスレッドでできそうということなので、実験をしてみようと思ったのですが、さっそく壁にぶつかりましたので、ご指導お願いいたします。

    DLLは何をしているのか分からいので実験として、C++のランタイムコンポーネント(Universal Windows)で下記のようなコードを書きます。

    int WindowsRuntimeComponent1::Class1::aaa()
    {
    	char *a;
    	a = new char[10000000];
    	while (1) {
    		;
    	}
    	return 0;
    }

    C#側(Univaersal Windows)では

    ・・・・
            private async void button1_Click(object sender, RoutedEventArgs e)
            {
                var kyo = new xyz();
                int x = await kyo.kyosei();
                GC.Collect();
            }
        }
    
        class xyz:MainPage
        {
            public async Task<int> kyosei()
            {
                Func<int> asyncJob = () =>
                {
                    var aaa = new WindowsRuntimeComponent1.Class1();
                    aaa.aaa();
                    return 0;
                };
                int ret1 = await Task.Run(asyncJob);
                return ret1;
            }
        }

    という感じのプログラムを書いてあげます。

    button1を何度か押すとメモリが増え、答えも帰ってこないので、新しいボタンを作成して、強制終了をしたいと思うのですが、さっぱり見当が付かない状態です。



    2016年5月8日 3:58
  • 私が書いていた内容は前提として Desktop apps です。(しかも、スレッドではない)

    UWP だとすると、恐らく方法はないでしょう。
    2016年5月8日 4:10
    モデレータ
  • 了解しました。プロセスにスレッドにタスク。あまり理解していないので、すみませんでした。

    Desktop appsで書いたものもWindows MobileとかのUWPで使えるように、なぜ継承させなかったのだろう?

    2016年5月8日 5:38
  • Desktop appsで書いたものもWindows MobileとかのUWPで使えるように、なぜ継承させなかったのだろう?

    継承させても不幸な結果を招くだけだと思います。

    第一に、プロセッサが違います。
    アーキテクチャの違いますし、処理性能も大きく違います。
    従来の Desktop apps と同じバイナリを動かすことはハードウェア的に厳しいでしょう。

    第二に、利用できるリソースが違います。
    スマホに載っているメモリは 2GB だと多い方でしょうし、ストレージも 32GB といったものになってくるでしょう。

    第三に、操作方法が違います。
    Desktop apps の多くはキーボード+マウスを前提としています。
    対して、スマホやタブレットといったタッチ入力の文化と操作性が全然違います。
    タッチファーストとして UX を設計するなど、大きく作り直さないと、使い勝手の良いアプリとは言えません。

    なお、UWP では利用可能な API が制限されています。
    UWP において、ブラックボックス的な DLL はまず利用不可能だと思ってください。
    (UWP 対応をうたっている DLL ならよいですが)

    2016年5月8日 6:21
    モデレータ
  • >なお、UWP では利用可能な API が制限されています。
    > UWP において、ブラックボックス的な DLL はまず利用不可能だと思ってください。
    > (UWP 対応をうたっている DLL ならよいですが)

     こんなことをしだした背景にはプロセスメモリが増加する / 「System.OutOfMemoryException はユーザー コードによってハンドルされませんでした。」で止まる。が背景にありました。ラッパーだと落ち着くのが不思議に思ったからです。もしかしてIRandomAccessStream、BitmapEncoderUWP 対応ではないのかな?

     ところで、継承に関しては、Mobile(ARM?)に関してはハードの能力が理由にあったのですね。
     では、デバックする時に、X64にしたらまた違うのになるものなのだろうか? とふと素人的に感じてしまいました。


    2016年5月8日 9:20
  • では、デバックする時に、X64にしたらまた違うのになるものなのだろうか? とふと素人的に感じてしまいました。

    疑問とされていますが、私から見ると、何を疑問に感じているのか、つかみきれないので一言だけ。

    「x64 と x86 の関係については自分で学んでみましょう」

    2016年5月8日 10:26
    モデレータ
  • では、デバックする時に、X64にしたらまた違うのになるものなのだろうか? とふと素人的に感じてしまいました。

    疑問とされていますが、私から見ると、何を疑問に感じているのか、つかみきれないので一言だけ。

    「x64 と x86 の関係については自分で学んでみましょう」

     たしかに学ぶ必要性は大です。

    2016年5月11日 9:36