「GC.Collect」を実行すると、私のクラッシュが修正されていますが、私は理由を理解していません
質問
私は(C#でのNokia PCとの接続3.2のコード例から、)コードのこの部分を持っています:
DAContentAccessDefinitions.CA_FOLDER_INFO folderInfo =
new DAContentAccessDefinitions.CA_FOLDER_INFO();
folderInfo.iSize = Marshal.SizeOf(folderInfo); //(32)
IntPtr bufItem = Marshal.AllocHGlobal(folderInfo.iSize);
//I often get a AccessViolationException on the following line
Marshal.StructureToPtr(folderInfo, bufItem, true);
私はこのの開始時にGC.Collect()
を実行する場合は、、その後、私はAccessViolationException
を得ることはありません。しかし、私は必要な場合に限り、この関数を遅くする必要はありません。私は成功せず、様々な場所でGC.Keepalive
を入れてみました。
CA_FOLDER_INFO
は以下のように定義されます
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct CA_FOLDER_INFO
{
public int iSize;
public int iFolderId;
public int iOptions;
public string pstrName;
public string pstrPath;
public int iSubFolderCount;
public IntPtr pSubFolders;
public IntPtr pParent;
}
私は、この例では、文字列のいずれかを必要とし、IntPtr
にその定義を変更すると、例外が離れて行くように思われません。
何ここで起こっている、そして何と例外を防止するための正しい方法は何ですか?
解決
あなたの問題は、それが(時には無効である)2つの文字列のポインタを解放しようとするので、あなたはMarshal.StructureToPtrに真渡しているということです。あなたは、あなただけのヒープ上にそのメモリを割り当てられているため、このインスタンスではfalseを渡す必要があります。 (すなわち、そこに解放するためには何もありません)。
他のヒント
あなたはMarshal.Sizeof(bufItem)とMarshal.Sizeof(folderInfo)が同じであることを確認していますか?
そして、あなたは文字列を初期化していないことかもしれないという事実?あなたは、彼らがのIntPtr(IntPtr.Zeroデフォルト)しているときにエラーが出ていないと言うので、あなたは、バッファアイテムをマーシャリングしようとする前に、私は空の文字列にそれらの両方を設定してみてくださいと思います。
の [編集] の
たぶん、あなたはその逆VISバッファハンドルを固定し、構造にそれをマーシャリングではなく、試してみてください。このような何かます:
DAContentAccessDefinitions.CA_FOLDER_INFO folderInfo;
GCHandle pinnedHandle = GCHandle.Alloc(buffItem, GCHandleType.Pinned);
folderInfo = (DAContentAccessDefinitions.CA_FOLDER_INFO)Marshal.PtrToStructure(pin.AddrOfPinnedObject(), typeof(DAContentAccessDefinitions.CA_FOLDER_INFO));
pin.Free();
//folderInfo should contain the data from buffItem
あなたの元folderInfo
へのポインタを取得するために、固定キーワードを使用します。
これは、アンマネージリソースが何かによって解放されていないことが考えられます。あなたが実装を使用しているものかどうかを確認してください IDisposableをともしそうなら、using { }
ブロックでそれをラップします。