2009-06-15 106 views
1

我有这样一段代码(从诺基亚PC连接3.2示例代码,在C#):运行“GC.Collect的”修复我的崩溃,但我不明白为什么

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似乎使异常消失。

这是怎么回事,防止异常的正确方法是什么?

+4

不要忘记在一个try-finally包装中,当你完成bufItem时调用Marshal.FreeHGlobal。 – sisve 2009-06-15 10:32:36

回答

5

你的问题是,你传递真实Marshal.StructureToPtr所以尝试释放两个字符串指针(这有时是无效的)。您需要在此实例中传递false,因为您只是在堆上分配了该内存。 (即没有空闲空间)。

0

使用fixed关键字来获取指向原始folderInfo的指针。

0

这可能是非托管资源不被释放的东西。检查你正在使用的任何东西是否实现IDisposable,如果是,则将其包装在using { }块中。

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 
+1

将两个字符串字段设置为“”或String.Empty不会导致AccessViolationException消失... – Greg 2009-06-16 10:59:26

+1

尺寸相同。 – Greg 2009-06-16 11:00:00

相关问题