之前没有访问的访问冲突

Dav*_*own 3 .net c# pinvoke graphviz access-violation

我是P/如图所示调用Graphviz .当我写这篇博客文章时,代码运行得很好.现在,我把在一起的HttpModule呈现使用代码Graphviz的图形,但我得到了AccessViolationExceptionagmemread.

// Native signature
Agraph_t agmemread(char *);

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

// Usage
IntPtr g = agmemread(data);
Run Code Online (Sandbox Code Playgroud)

就像我说的,这之前完美无缺.但现在,我无法让我的代码适用于任何事情.即使我基于相同代码的旧Graphviz应用程序也不再起作用.

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

编辑:我尝试string改为StringBuilder,但产生了相同的结果.然后,我添加了一个MarshalAs属性:

static extern IntPtr agmemread([MarshalAs(UnmanagedType.LPWStr)] string data);
Run Code Online (Sandbox Code Playgroud)

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

Han*_*ant 6

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

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

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

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

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