Memory AccessViolationException 错误从 C# 调用 DLL

Posted

技术标签:

【中文标题】Memory AccessViolationException 错误从 C# 调用 DLL【英文标题】:Memory AccessViolationException Error Calling DLL From C# 【发布时间】:2008-10-17 13:40:37 【问题描述】:

我在从 C# 调用已编译的 DLL 时遇到奇怪的内存读/写错误。我使用 DllImport 来获取我们需要的函数的句柄,该函数将返回值写入指向 int 的参数指针(即 int* out)。该函数在一个线程内被多次调用,并在第一个线程的执行生命周期内成功运行。但是,如果在第一个线程完成后启动另一个线程,则对外部 dll 的调用会引发 AccessViolationException。由于来自第一个线程的多次调用成功执行,我认为这与第一个线程没有释放指向相关整数参数的指针(?)有关。如果是这样,我怎样才能显式释放该内存?或者,也许有人对这里可能发生的事情有不同的见解?非常感谢。

编辑:丹尼要求提供更多细节,我很乐意答应。这里是调用外部例程的地方:

    int success = -1;
    unsafe
    
        int res = 0;
        int* res_ptr = &res;
        int len = cmd.ToCharArray().Length;
        int* len_ptr = &len;
        CmdInterpreter(ref cmd, len_ptr, res_ptr);
        success = *res_ptr;
    

其中 CmdInterpreter 定义为:

    [DllImport("brugs.dll", EntryPoint="CmdInterpreter", 
        ExactSpelling=false, CallingConvention = CallingConvention.StdCall)]
    public static unsafe extern void CmdInterpreter(ref string cmd, int *len, int *res);

如果有任何其他有用的信息,请告诉我。谢谢!

【问题讨论】:

需要一些代码示例。这还不够具体。我们需要查看您的实现(即调用的 C# 代码)以提供帮助。 你能告诉我们原生代码吗?查看 DLLImport 函数,我相信您有一个错误,但在我看到本机签名之前无法确定 我希望可以。不幸的是,我无权访问源代码。但同样,如果这是签名的错误,您认为来自第一个线程的所有调用都会成功运行吗?谢谢。 【参考方案1】:

鉴于该问题仅在涉及多个线程时出现,可能是命令解释器 DLL 正在使用某种线程本地存储并且执行不正确。它还可能与第二个线程(产生错误的那个)的 COM 初始化状态有关。

如果您在第一个/主线程上对 DLL 进行任何调用之前启动新线程并让它调用 DLL 会发生什么,这会很有趣。如果它有效,那可能支持线程本地存储理论。如果它失败了,那将支持 COM 状态理论。

【讨论】:

【参考方案2】:

可能是 [DllImport]。如果您发布 [DllImport] 签名和 DLL 的原型,也许我们可以发现问题。

我了解到托管、本机和 COM 互操作团队在 CodePlex 上发布了 PInvoke 互操作助手。 http://www.codeplex.com/clrinterop/Release/ProjectReleases.aspx?ReleaseId=14120

【讨论】:

谢谢greguzelac,我已经发布了导入签名。但是,如果签名有问题,它不会在第一次调用时失败吗?同样,它在整个第一个线程中完美运行,只有当第二个线程调用它失败的方法时。再次感谢。

以上是关于Memory AccessViolationException 错误从 C# 调用 DLL的主要内容,如果未能解决你的问题,请参考以下文章

Memory和Storage有啥区别

@ Buffer.Memory ^和Buffer.Memory有什么区别?

object_store_memory 和 redis_max_memory 有啥关系?

在unittest期间全局禁用joblib.memory缓存

C++11 memory_order_acquire 和 memory_order_release 语义?

C F出现out of memory怎么办