【问题标题】:Access violation where there wasn't one before之前没有的访问冲突
【发布时间】:2010-01-30 08:17:01
【问题描述】:

我正在向 Graphviz as shown here 发起 P/调用。当我写那个博客条目时,代码运行得很好。现在,我正在整理一个 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 无法正确读取字符串并返回空指针。

【问题讨论】:

  • 相同的数据?操作系统位数相同(32/64 位)?你知道 AV 是否​​真的在那条线上,还是在 agmemread() 调用中的某个地方?
  • 相同的数据,相同的操作系统。 agmemread 是一个原生函数,所以我不知道它在后台做了什么导致访问冲突。
  • MarshalAs(UnmanagedType.LPStr) 怎么样?我对 Graphviz 一无所知,但 Bing 告诉我参数是“char *”,而不是 wchar。
  • LPStr 也不起作用。我试过StringBuilder,因为参数是char *,但什么也没做。 LPWStr 是唯一接近工作的东西。

标签: c# .net pinvoke graphviz access-violation


【解决方案1】:

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

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

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

找到真正的麻烦制造者非常困难,您只需几个面包屑即可找出可能出了什么问题。当您拥有 C/C++ 源代码时非常困难,但使用调试分配器在调试版本中运行它会有所帮助。没有源代码是不可能的。

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

【讨论】:

  • 我相信你一针见血!在访问冲突异常之前,我一直在向agmemread 提供无效数据,导致它失败。所以,考虑到你所说的,我认为agmemread 失败时可能没有正确清理。我重新启动了我的机器以获得一个干净的状态,现在它与原始代码和正确的输入数据一起工作得很好。但是,我开始尝试通过多次无效调用agmemread 来重现它,但这次它没有表现出任何访问冲突。很奇怪。也许我会向 Graphviz 开发人员发送电子邮件。
  • 顺便说一句,当我说“导致它失败”和“进行多次无效调用”时,我的意思是函数返回一个空指针,这是它在出错时应该做的发生。
  • 当然,通常测试最少的代码是错误处理代码。
  • 我向 Graphviz 团队提交了一份错误报告,他们认为这与解析器如何尝试从错误中恢复有关。希望它很快得到解决。感谢您再次为我指明正确的方向!
  • 我在if (gvLayout(gvc, g, layout) != SUCCESS) ... 得到了与 GraphViz 互操作 AccessViolationException 类似的东西@ 失败率可能是 4 分之一,但总是在那个地方。有更新吗?
猜你喜欢
  • 2013-07-13
  • 2013-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多