我有这段代码(来自诺基亚PC连接3.2示例代码,在C#中):
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
似乎会使异常消失。
这里发生了什么,以及防止异常的正确方法是什么?
答案 0 :(得分:5)
你的问题是你将true传递给Marshal.StructureToPtr,所以它试图释放两个字符串指针(有时无效)。您需要在此实例中传递false,因为您刚刚在堆上分配了该内存。 (即那里没有任何东西可以释放)。
答案 1 :(得分:0)
使用fixed关键字获取指向原始folderInfo
的指针。
答案 2 :(得分:0)
可能是某些东西没有释放非托管资源。检查您使用的是否有任何实现IDisposable,如果是,请将其包装在using { }
块中。
答案 3 :(得分:0)
你确定Marshal.Sizeof(bufItem)和Marshal.Sizeof(folderInfo)是一样的吗?
而且,也许您没有初始化字符串这一事实?因为你说你在IntPtr(默认为IntPtr.Zero)时没有得到错误,所以在尝试编组缓冲项之前,我会尝试将它们都设置为空字符串。
<强> [编辑] 强>
也许您应该尝试固定缓冲区句柄,并将其整理到结构中,而不是相反。像这样:
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