【问题标题】:.net - AccessViolation when interacting with native DLL for the first time.net - 第一次与本机 DLL 交互时的 AccessViolation
【发布时间】:2010-01-27 19:22:39
【问题描述】:

这有点奇怪,也是我第一次涉足 .net 世界,所以我希望我错过了一些基本的东西 :) 背景:

我有一个本机/Qt c++ DLL,我将其打包用于 .NET,在本例中为 C#。我有一个成功使用这个 DLL 的 Qt 应用程序,没有内存泄漏等。我已经为这个库创建了一个 c++/CLI 包装器,我可以通过它成功调用本机代码。但是,我注意到,根据我第一次与托管 DLL(以及本机 DLL)交互的方式,我会看到 AccessViolation 异常。

如果我首先在进程(不是 .net)堆上从本机 DLL 分配一个对象,那么一切都会按预期工作。但是,如果我通过在堆栈上创建来自本机 DLL 的对象与它进行交互,然后在堆上分配一个本机对象,我稍后会在不相关的本机 DLL 代码中获得 AccessViolation 异常。事实上,我只需要分配原生对象(不再引用它)就可以看到这些错误。

堆栈与堆的问题当然可能是一个红鲱鱼,但它是 100% 可重现的,所以看起来至少是一个很好的线索。有小费吗?谢谢!

【问题讨论】:

  • 我们能看一些代码吗?你在使用 p/invoke 吗?
  • 废话 - 我目前无法访问代码(在另一台机器上),但我没有使用 p/invoke。我从 C++/CLI DLL 直接调用本机 DLL。我一直小心不要将任何指向 gcnew 对象的指针传递到本机代码中——我已经做到了这一点,我使用了 pin_ptr,如下所示。我会尽快发布一些样本 - 抱歉!感谢您的回复。

标签: .net memory dll


【解决方案1】:

你是如何在堆上分配东西的?

如果您正在分配托管对象(gcnew 等),然后将它们传递给非托管代码,或者只是将指向现有托管对象的指针传递给非托管代码,那么垃圾收集器就会出现并收集或重新定位它们。这会导致您的非托管代码具有垃圾指针,因此(很可能)访问冲突

为了提供更多帮助,我们几乎肯定需要查看代码 sn-p。干杯

【讨论】:

    【解决方案2】:

    我同意 Orion Edwards 的观点,这很可能是 GC 问题。为了可能帮助解决它,您需要“固定”对象,以便 GC 不会收集它。这有它的陷阱,所以要小心。

    查看这篇文章了解更多信息:

    Copying and Pinning

    固定将数据暂时锁定在其当前内存位置,从而防止它被公共语言运行时的垃圾收集器重新定位。封送拆收器固定数据以减少复制开销并提高性能。数据的类型决定了在编组过程中是复制还是固定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多