我是 P/调用 Graphviz as shown here .当我写那篇博文时,代码工作得很好。现在,我将一个 HttpModule
放在一起,它使用该代码呈现 Graphviz 图,但我在 agmemread
处收到一个 AccessViolationException
。
// 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 都是一样的。
编辑: 我尝试将 string
更改为 StringBuilder
,但结果相同。然后,我添加了一个 MarshalAs
属性:
static extern IntPtr agmemread([MarshalAs(UnmanagedType.LPWStr)] string data);
有了它,我不再得到 AccessViolationException
,但 Graphviz 无法正确读取字符串并返回空指针。
最佳答案
非托管代码很少需要 C# 的大量帮助才能开始生成访问冲突。您的 P/Invoke 签名没有任何问题,这不可能是原因。
非托管代码中最常见的 AV 来源是堆损坏。 C/C++ 代码没有垃圾收集器,必须显式管理内存。它不仅必须负责释放内存(否则会泄漏),还负责分配正确的大小并确保写入已分配内存的代码不会写入已分配内存块的末尾或写入已经释放的内存。最后一个要求是 C/C++ 代码经常失败的地方。
堆损坏的问题在于它极难诊断。它可能会被忽视很长一段时间。典型的损坏是内部堆结构被破坏,或者另一个堆分配中的数据被覆盖。直到稍后释放堆 block 或使用覆盖的数据时,这才会导致问题。生成异常的代码实际上并不对之前造成的损害负责。这让您误入歧途,试图找到问题的根源。
找到真正的麻烦制造者非常困难,您只有几个面包屑可以找出可能出了什么问题。当您拥有 C/C++ 源代码时,这非常困难,但在带有调试分配器的调试版本中运行它会有所帮助。如果没有源代码,这是不可能的。
除非您可以从之前调用的 API 中找出使用 API 的问题,否则您将需要供应商或支持小组的帮助才能真正解决这个问题。祝你好运。
关于c# - 以前没有的访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2167263/