以前没有发生过的访问冲突

2024-03-22

我正在 P/调用 Graphviz如图所示 http://implicitoperator.com/blog/2009/12/24/rendering-an-in-memory-graphviz-image-with-c.html。当我写那篇博客文章时,代码运行得很好。现在,我正在整理一个HttpModule使用该代码渲染 Graphviz 图表,但我得到了AccessViolationException at agmemread.

// Native signature
Agraph_t agmemread(char *);

// P/Invoke Signature
[DllImport(LIB_GRAPH)]
private static extern IntPtr agmemread(string data);

// Usage
IntPtr g = agmemread(data);

就像我说的,这之前效果很好。但现在,我无法让我的代码在任何情况下工作。甚至我基于相同代码的旧 Graphviz 应用程序也不再工作了。

我可能改变什么会导致这种情况?我什至还没有下载新版本的 Graphviz 或其他任何东西,所以 DLL 都是一样的。

EDIT:我尝试改变string to StringBuilder,但这产生了相同的结果。然后,我添加了一个MarshalAs属性:

static extern IntPtr agmemread([MarshalAs(UnmanagedType.LPWStr)] string data);

有了这个,我不再得到AccessViolationException,但是 Graphviz 无法正确读取字符串并返回空指针。


非托管代码很少需要 C# 的大量帮助才能开始生成访问冲突。您的 P/Invoke 签名没有任何问题,这不可能是原因。

非托管代码中最常见的 AV 来源是堆损坏。 C/C++ 代码没有垃圾收集器,必须显式管理内存。它不仅必须负责释放内存(否则会泄漏),还负责分配正确的大小并确保写入分配的内存的代码不会超出分配的内存块的末尾或写入已经释放的内存。最后一个要求是 C/C++ 代码经常失败的地方。

堆损坏的问题在于它极难诊断。它可能会在相当长一段时间内被忽视。造成的典型损害是内部堆结构被破坏,或者另一个堆分配中的数据被覆盖。这不会导致问题,直到稍后释放堆块或使用覆盖的数据时。生成异常的代码实际上并不对之前造成的损害负责。这会让你在试图找到问题根源时走上错误的道路。

找到真正的麻烦制造者非常困难,你只能通过一些线索来找出可能出了问题的地方。当您拥有 C/C++ 源代码时,这非常困难,但使用调试分配器在调试版本中运行它会有所帮助。如果没有源代码,这是不可能的。

除非您可以从之前的调用中查明使用 API 的问题,否则您将需要供应商或支持小组的帮助才能真正解决此问题。祝你好运。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

以前没有发生过的访问冲突 的相关文章

随机推荐