VB.net2003にて、FORTRANのexeファイルが出力した文字列を
共有メモリを介してVBで取得する機能を作っています。
タイマーにより逐次データを取得する仕組みなのですが
徐々にメモリを消費し、OutOfMemoryとなってしまいます。
Private Declare Sub CopyMemoryStruct Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As SEND_DATA, ByVal Source As Integer, ByVal Length As Integer)
'構造体定義
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
Public Structure STRUCT_DATA
<VBFixedString(DataLength), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=DataLength)> _
Dim msg As String
ReadOnly Property getMsg() As String
Get
Return msg
End Get
End Property
Sub msgSet(ByVal str As String)
msg = str
End Sub
End Structure
'データ取得メソッド
Private Sub getDataMethod(...)
Dim data As STRUCT_DATA
Dim str As String
Dim lpFileMap As Integer '共有メモリのマッピングアドレス
'構造体にデータを格納
CopyMemoryStruct(data, lpFileMap, Marshal.SizeOf(data))
str = sendData.getMsg()
'ここでstrを用いた処理を行いますが何もなくても
'OutOfMemoryになります
End Sub
複数のマッピングファイルに対してこのメソッドを呼ぶ構成です。
マッピングファイルのオープン/クローズは
このメソッドの呼び出し元で行っています。
上のプログラムで何かしら原因となる箇所がありましたら
ご指摘いただけますでしょうか。
このメソッドを抜けたときに構造体dataは
メモリから解放されると思っているのですが。
VBでの構造体及び共有メモリについて明るくないので
的外れな質問をしているかもしれませんが、
どうぞよろしくお願いいたします。
ByVal Source As Integer?はいいのかな
Private Declare Sub CopyMemory Lib "kernel32"
Alias "RtlMoveMemory" ( _
Destination As Any, Source As Any, ByVal length As Long)
As AnyはVB6でしたね、ByVal Source As Longとか
編集 削除> Dim lpFileMap As Integer '共有メモリのマッピングアドレス
そういった物に対しては、IntPtr 型を使うべきかと。
> ご指摘いただけますでしょうか。
ソースから想像すると、共有メモリから得たい値は ANSI 形式の文字列の
ようですが、そこに含まれるデータは、ASCII 文字だけですか?
それとも、2バイト文字を含んだ Shift_JIS データでしょうか?
もし、2バイト文字を含んでいるのだとしたら、構造体に指定している
DataLength というのは、「バイト数」と「文字数」のどちらの意図ですか?
> VBでの構造体及び共有メモリについて明るくないので
構造体のマーシャリングは、それなりの前提知識が必要ですよ。
特に、文字列を含んでいるような場合には。
構造体の前に、単純なバイト配列で受け取る事から始めては如何でしょう?
たとえば、
Dim ptr As IntPtr = [参照先のアドレス]
Dim buf(DataLength - 1) As Byte
Marshal.Copy(ptr, buf, 0, DataLength)
Dim str As String = System.Text.Encoding.GetEncoding("Shift_JIS").GetString(buf)
のようにするとか。
(検証しようが無いので、保証はできませんけれども)
> 上のプログラムで何かしら原因となる箇所がありましたら
まずは、プログラムの仕様(共有メモリ上のデータ配置など)を
提示してもらわないことには、どうにもならないです。
(属性の指定が正しく行われているかどうかすら、判断できません)
そもそも、STRUCT_DATA の実装意図もわかりません。
(1) getMsg とくれば、対義語 は setMsg だと思うのですが、
なぜ、msgSet なのでしょうか? (まぁ、これは本題とは無関係ですが)
(2) msg フィールドを使って、文字列にアクセスできるというのに、
わざわざ、プロパティ/メソッドを用意しているのはなぜですか?
(3) 代入をメソッド化しているのに、取得がメソッドでは無いのは何故ですか?
(というよりも、プロパティを Get/Set の両対応にすれば済むような)
>> やじゅさん
ByVal Source As Long ではマズイのでは…?
それからここは [VB2-VB6専用] の掲示板なので、2003 は対象外です。
もし続けるのであれば、隣の掲示板に移動してくださいね。
やじゅさん
魔界の仮面弁士さん
ご意見ありがとうございます。
参考にさせていただきます。
あと、質問内容のアバウトさや板間違いについては
申し訳ありません。以後、気をつけます。