运行“GC.Collect” 修复了我的崩溃,但我不明白为什么

发布于 2024-07-25 01:03:33 字数 1090 浏览 1 评论 0原文

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

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

I have this piece of code (from the Nokia PC connectivity 3.2 example code, in 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);

If I run GC.Collect() at the start of this, then I don't get an AccessViolationException. But I don't want to slow down this function unless necessary. I've tried putting GC.Keepalive in various places, but without success.

CA_FOLDER_INFO is defined as:

    [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;
    }

I don't, in this instance, require either of the strings, and changing their definitions to IntPtr seems to make the exception go away.

What is going on here, and what is the correct way to prevent the exception?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

祁梦 2024-08-01 01:03:33

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

Your problem is that you're passing true to Marshal.StructureToPtr so it attempts to free the two string pointers (which are sometimes invalid). You need to pass false in this instance since you just allocated that memory on the heap. (i.e. there's nothing to free there).

匿名。 2024-08-01 01:03:33

您确定 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

Are you sure Marshal.Sizeof(bufItem) and Marshal.Sizeof(folderInfo) are the same?

And, maybe the fact that you aren't initializing the strings? Since you say you don't get the error when they are IntPtr (which defaults to IntPtr.Zero), I'd try setting them both to empty strings before you try marshaling the buffer item.

[Edit]

Maybe you should try pinning the buffer handle, and marshaling that to the structure, rather than vis versa. Something like this:

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
陪你搞怪i 2024-08-01 01:03:33

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

Use the fixed keyword to get a pointer to your original folderInfo.

如此安好 2024-08-01 01:03:33

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

It could be that unmanaged resources aren't being released by something. Check to see if anything you're using implements IDisposable and if so, wrap it in a using { } block.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文