运行“GC.Collect的”修复我的崩溃,但我不明白为什么
题
我有这样一段代码(从诺基亚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
似乎使异常消失。
这是怎么回事,什么是防止异常的正确方法是什么?
解决方案
您的问题是,你传递真实Marshal.StructureToPtr所以尝试释放两个字符串指针(这有时是无效的)。你需要,因为你只是在堆中分配内存在这种情况下通过假。 (即没有什么释放那里)。
其他提示
您确定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
使用固定的关键字,以得到一个指向原来的folderInfo
。
这可能是因为非托管资源没有被释放的东西。检查是否有任何你使用工具 IDisposable的和如果是这样,它包装在一个using { }
块。
不隶属于 StackOverflow