非托管 DLL 的访问冲突 [英] Access Violation with unmanaged DLL

查看:24
本文介绍了非托管 DLL 的访问冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我们使用供应商提供的非托管 DLL,它允许我们访问特定仪器.感兴趣的特定功能在头文件中指定如下:

Currently, we use an unmanaged DLL from a vendor that allows us to access a particular instrument. The particular function of interest is specified in a header file as this:

extern "C" short CCONV acq_get_board_count ();

在我的应用程序中,我有 pinvoke 语句:

In my application, I have the pinvoke statement:

public class bograms
{
    [DllImport("bograms.dll", EntryPoint = "acq_get_board_count", CallingConvention = CallingConvention.StdCall)]
    public static extern short acq_get_board_count();
}

现在,在我的代码中,我试图处理冗余,所以我创建了一个试图保持运行的计时器:

Now, in my code I am attempting to handle redundancy, so I create a timer that attempts to keep things running:

public class Instrument
{
    private System.Threading.Timer keepAliveTimer;
    public Instrument()
    {
        keepAliveTimer = new Timer(new TimerCallback(this.KeepAlive), null, 0, 300000);
    }

    void KeepAlive(object state)
    {
        if(instrumentIsUninitialized) // some check that accomplishes this
        {
            Console.WriteLine("Some status statements"); // in console
            short numBoards = bograms.acq_get_board_count();
            Console.WriteLine("Initialization caught {0} boards.", numBoards); // not in console
        }
    }
}

定时器的第一个滴答声,它得到零个板(大概是因为硬件没有完成初始化),并将两个消息打印到控制台.但是,在第二个滴答声中,我在 bograms.dll 中收到一个 APPCRASH 错误 0xc0000005,我发现这是一个访问冲突错误.在调用周围放置 try/catch 不会捕获错误.第一行在控制台中,第二行不在.在调试转储文件时(尽我有限的专业知识),此调用似乎发生了错误.

The first tick of the timer, it gets zero boards (presumably because the hardware is not finished initializing), and prints both messages to the console. However, the second tick, I get an APPCRASH error 0xc0000005 in the bograms.dll, which I've found to be an Access Violation error. Putting try/catch around the call does not catch the error. The first line is in the console, the second line is not. When debugging the dump file (to the best of my limited knowhow), the error seems to occur on this call.

我的 pinvoke 语句有误吗?这是一个如此简单的功能,我无法相信它会是这样,但我是否遗漏了什么?定时器导致的线程是否导致某种类型的问题?

Is my pinvoke statement wrong? It's such a simple function that I can't believe it would be, but am I missing something? Is the threading due to the timer causing some type of problem?

我猜第一次调用将其置于某种类型的状态,导致第二次调用失败,尤其是在考虑到在幕后进行的硬件初始化时.如果是这种情况,是否有任何方法可以卸载驱动程序 DLL 以便它可以重置回它应该处于的初始状态?

I'm guessing the first call puts it into some type of state that results in the second call's failure, especially when considering the hardware initialization going on behind the scenes. If this is the case, is there any way to unload the driver DLL so it can reset back to the initial state it should be in?

或者还有什么你能想到的吗?

Or are there any other things you can think of?

推荐答案

马上想到的一件事是 API 是否可以安全地跨线程使用.System.Threading.Timer 回调进入一个 ThreadPool 线程,因此每次都可能不同.某些 API 具有线程关联性要求,这意味着它们只能从单个线程调用.取而代之的是,如果对同一 API 的两个调用同时发生,仍然可能存在一些并发问题.最后你可能会发现问题与线程无关.我只是想提出一种可能的解释.

One thing that immediately comes to mind is whether the API can be used safely across threads. The System.Threading.Timer callbacks come in on a ThreadPool thread so it could be different each time. Some APIs have thread affinity requirements which means that they can only be called from a single thread. In lieu of that there still may be some concurrency problem if two calls to the same API occur simultaneously. In the end you may find out that the problem has nothing to do with threading. I am just trying to present one possible explanation.

这篇关于非托管 DLL 的访问冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆