1

我有这段代码(来自诺基亚 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似乎会使异常消失。

这里发生了什么,防止异常的正确方法是什么?

4

4 回答 4

5

您的问题是您将 true 传递给 Marshal.StructureToPtr ,因此它尝试释放两个字符串指针(有时无效)。在这种情况下,您需要传递 false ,因为您刚刚在堆上分配了该内存。(即那里没有什么可以释放的)。

于 2009-06-16T15:57:32.633 回答
0

使用 fixed 关键字获取指向原始folderInfo.

于 2009-06-15T10:09:57.833 回答
0

可能是某些东西没有释放非托管资源。检查您正在使用的任何东西是否实现了IDisposable,如果是,请将其包装在一个using { }块中。

于 2009-06-15T10:16:29.550 回答
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
于 2009-06-15T21:39:29.120 回答