- - PR -
C# インスタンスのアドレスを固定したい
1
投稿者 | 投稿内容 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2004-12-21 14:29
構造体やクラスのポインタを使っています。通常はポインタを使用するたびにfixedキーワードでインスタンスを局所的に固定しています。けれど、より広域でインスタンスを固定したい場合があります。固定したいのは特定のインスタンスのみなので、GCの機能そのものは常時働き続けるようにしたいです。
特定のインスタンスのみ固定する方法(つまりGCの移動対象から外す)、および移動を再開する方法を教えてください。 | ||||||||||||||||
|
投稿日時: 2004-12-22 00:48
こんばんは、meiです。
クラスのインスタンスに対してfixedはできません。参照型もしくは、参照型を含む型に対してfixedを行うとコンパイルエラーが出ませんでしたか? お望みの動作はC#が対象とするプログラミング領域ではないと思います。(Managed)C++などを使うべきでしょう。Marshal.AllocHGlobalメソッドを使えばGC管理外のメモリは確保できますが、Managedなオブジェクトを生成するような領域としては使えません。なので、オブジェクトではなく純粋なメモリ領域としてUnmanagedな世界とやり取りするしか無いでしょう。 | ||||||||||||||||
|
投稿日時: 2004-12-22 12:59
長期間、データを保持し、広いスコープでデータアクセスしたいのであれば、
Singletonのパターンを使うという手もあります。 ただし、クラススコープのオブジェクトが何らかのタイミングでGCされるかも知れないため、完全な代替案とはならないかもしれません。 速度的には劣ってしまいますが、ファイルやDBに保持しておくという方法も考えられます。 | ||||||||||||||||
|
投稿日時: 2004-12-28 23:47
ご回答ありがとうございます。
C#で確保した領域をDMAでアクセスしたいので今回は残念ながらファイルは活用できません。私はVB6→C#へ移行したユーザーでC++の経験が無いので、可能な限りC++は避けたいと考えています。どうしても方法が無ければC++を学ぶしかないのですが…。 試していないのですが、専用のThreadを作成し、fixedのスコープの中でで必要な期間だけThreadStateをSuspendさせるというのは良い方法でしょうか? (問題があるような気がしますが…) _________________ | ||||||||||||||||
|
投稿日時: 2004-12-29 01:20
GC を阻害するのはよくないです。
なら、Marshal.AllocHGlobal() した領域を使えばいいんじゃないでしょうか。 _________________ // 渋木宏明 (Hiroaki SHIBUKI) // http://hidori.jp/ // Microsoft MVP for Visual C# // // @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/ | ||||||||||||||||
|
投稿日時: 2004-12-29 16:42
ご回答ありがとうございます。
Marshalクラスについていくつか分からない点があります。 Q1.AllocHGlobal()とAllocCoTaskMem()の違いは? Q2.Marshal.AllocHGlobal()あるいはMarshal.AllocCoTaskMem()で確保された領域は、明示的にFreeHGlobal()あるいはFreeCoTaskMem()を実行するまで(永久に)固定領域が確保されつづけると考えて正しいでしょうか? (Q3.Q4はある意味Q2と同じ質問ですが) Q3.Marshal.AllocHGlobal()あるいはMarshal.AllocCoTaskMem()とひもづいたポインタあるいはIntPtrがスコープから外れても領域は確保されつづけるのでしょうか?また、 Q4.アプリケーションがFreeHGlobal()あるいはFreeCoTaskMem()を実行しないで終了してしまった場合、確保された領域は宙に浮いたまま残ってしまうのでしょうか?(メモリーリーク) Q5.(Q4が真である場合)アプリケーションに予期せぬエラーが発生しても確実にFreeHGlobal()あるいはFreeCoTaskMem()が実行される良い工夫はあるでしょうか?例えば領域を操作するための専用クラスを作成しておいて、Dispose()をoverrideしてFreeHGlobal()あるいはFreeCoTaskMem()を仕込めばOKでしょうか。 宜しくお願いします。 _________________ | ||||||||||||||||
|
投稿日時: 2004-12-29 17:22
ヘルプにも説明があるはずですが、内部で呼び出している API の違いです。 AllocHGlobal() は GlobalAlloc() API を、AllocCoTaskMem() は CoTaskMemAlloc() API をそれぞれ内部で呼び出しています。
プロセスのアドレス空間内でのアドレスは固定されています。
GC とは無関係なメモリ確保ですから、参照を失っても自動的に改修されることはありません。ほったらかして置けばリークします。
シナリオ次第なんでなんとも。 [quote] 例えば領域を操作するための専用クラスを作成しておいて、Dispose()をoverrideしてFreeHGlobal()あるいはFreeCoTaskMem()を仕込めばOKでしょうか。 [quote] なんてのもひとつの方法ではありますね。 _________________ // 渋木宏明 (Hiroaki SHIBUKI) // http://hidori.jp/ // Microsoft MVP for Visual C# // // @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/ |
1