Visual Studio - 如何调试 C# 类库中的堆错误

本文关键字:类库 错误 调试 Studio 何调试 Visual | 更新日期: 2023-09-27 17:47:22

我在 C++ 应用程序中通过 COM 调用的 C# 库模块中收到堆损坏错误。具体错误为:

堆:已修改自由堆块 4b61bb8 在 4b61be8 被释放
后 ...
这可能是由于 堆损坏,并指示 [应用程序]中的错误.exe 或它已加载的任何 DLL。

调用堆栈的顶部是:

CustomMarshalers.dll!System.Runtime.InteropServices.CustomMarshalers.EnumeratorViewOfEnumVariant.MoveNext() + 0x168 bytes

现在我的理解是.NET应该缓解内存问题,而不是使更多的内存问题无法解决。然而,我想不出我可能正在做任何事情来导致内存错误,或者我该如何尝试修复它。该特定模块使用 Microsoft.VisualStudio.VCProjectEngine .NET 组件通过非常简单的迭代器迭代 VC 项目文件。在迭代 VCProject 筛选器(文件夹)中的文件时,它在 foreach 语句中中断,在成功执行了大约 100 次调用后。正在破坏的实际代码是:

    IVCCollection CollectionFiles = (IVCCollection)FolderInProject.Files;
    foreach (VCFile File in CollectionFiles)
    {
        [...]
    }

我怎么可能去调试这个?

更新:

当我从纯 C# 控制台应用程序(不涉及 COM 或本机代码)调用 if 时,我得到:

类型的未处理异常 "System.AccessViolationException" 发生在 [组件] 中.dll

附加 信息:尝试读取或 写保护内存。这通常是 指示其他内存 腐败。

仍然不知道我该如何调试它。显然某处发生了内存错误...但是,如何在内存模型甚至没有公开的纯托管代码中跟踪它呢?

Visual Studio - 如何调试 C# 类库中的堆错误

看起来您的 COM 接口未正确封送参数/返回变量,导致 GC 意外释放托管内存或由于某些不正确的封送处理而导致非托管内存被丢弃。通过为 COM 组件构建自己的主互操作程序集,可以对创建的 COM 接口进行更精细的控制。只需稍加工作,即可检查 COM 对象上的违规方法,并确保其所有参数都具有正确的元数据,以确保它们被正确封送。

现在,另一种可能性是你正确地封送了所有内容,但你没有完全正确调用接口,表现为参数的不当使用,最终会丢弃非托管内存。跟踪这些不太有趣,尤其是在您无权访问 COM 源的情况下。

一个技巧是允许程序在调试器外部崩溃,单击"调试",这将打开选取 JIT 调试器窗口。然后选中"选择调试引擎"(或类似内容),并确保勾选"托管"和"本机"复选框。出现的 VS 实例应该在死亡的实际代码中被破坏,而不是在最接近死亡的托管代码中被破坏。