1

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

HEAP: Free Heap block 4b61bb8 在被释放后修改为 4b61be8
...
这可能是由于堆损坏,并表明 [app].exe 或它已加载的任何 DLL 中的错误。

调用堆栈的顶部是:

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

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

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

我怎么可能去调试呢?

更新:

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

[component].dll 中出现“System.AccessViolationException”类型的未处理异常

附加信息:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

仍然不知道如何进行调试。显然某处发生了内存错误......但是我如何在内存模型甚至没有暴露的纯托管代码中追踪它?

4

1 回答 1

1

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

现在,另一种可能性是您正在正确地编组所有内容,但您并没有完全正确地调用接口,这表明自己对参数的不正确使用最终会破坏非托管内存。追踪这些内容就不那么有趣了,尤其是在您无法访问 COM 源代码的情况下。

一个技巧是让程序在您的调试器之外崩溃,单击“调试”,这会打开选择 JIT 调试器窗口。然后检查“选择调试引擎”(或类似的东西)并确保选中托管和本机复选框。出现的 VS 实例应该在实际死亡的代码中被破坏,而不是最接近死亡的托管代码。

于 2008-10-10T02:42:26.607 回答