之前没有访问的访问冲突

我是P /调用Graphviz ,如下所示 。 当我写这篇博客文章时,代码工作正常。 现在,我正在整理一个使用该代码渲染Graphviz图形的HttpModule ,但是我在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 ++代码经常失败的地方。

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

找到真正的麻烦制造者是非常困难的,你只需要一些面包屑来找出可能出错的地方。 拥有C / C ++源代码非常困难,但在调试版本中使用调试分配器运行它有帮助。 没有源代码时,这是不可能的。

除非您能够确定使用早期调用API的问题,否则您需要供应商或支持小组的帮助才能真正解决此问题。 祝好运。

我有同样的问题 – P/Invoke签名需要添加CallingConvention=CallingConvention.Cdecl. Graphviz库是C调用约定,而不是StdCall

看到这个post 。