• 动态调用DLL函数有时正常,有时报Access violation的异常


    动态调用DLL函数有时正常,有时报Access violation的异常

    动态调用DLL函数有时正常。有时报Access violation的异常


    typedef int (add *)(int a,int b);


    void test()
    {
        hInst=LoadLibraryA("aimdtl.dll");
       (FARPROC &)add=GetProcAddress(hInst,"add");
        add(1,2);
    }


    按这个代码运行。add函数有时OK,有时报Access violation的异常。看到提示。第一反应就是内存异常了,可是这是什么引起了内存异常呢?
    于是想着用一个变量来接收add的返回值看看。




    void test()
    {
        hInst=LoadLibraryA("aimdtl.dll");
       (FARPROC &)add=GetProcAddress(hInst,"add");
       int sum=add(1,2);
    }
    结果,add函数运行了之后。还是有时OK,有时报Access violation的异常。这会是什么原因?于是谷歌了下,有人提到,可能要加__cdecall。于是我果断改动代码。新代码例如以下:


    typedef int __cdecall (add *)(int a,int b);


    void test()
    {
        hInst=LoadLibraryA("aimdtl.dll");
       (FARPROC &)add=GetProcAddress(hInst,"add");
        add(1,2);
    }


    结果,add函数运行了之后,还是有时OK。有时报Access violation的异常。

    纠结了!为什么 !

    这时,想起在C中调用DLL函数时。须要用__stdcall。那是不是这里也要?马上改之!




    typedef int __stdcall (add *)(int a,int b);


    void test()
    {
        hInst=LoadLibraryA("aimdtl.dll");
       (FARPROC &)add=GetProcAddress(hInst,"add");
        add(1,2);
    }




    执行后,一切OK。问题至此已经解决。可这是为什么呢?于是回过头来看了看__stdcall和__cdecall的说法。


    _stdcall:Win32 API的调用协议,由被调用的函数清理堆栈,全部參数自右至左入栈。生成的代码中函数名有一个_做前缀和一个@和參数的总字节数(十进制)作后缀。它不支持可变參数,但它产生的代码比_cdecl短,由于没有每次调用后的清理堆栈的代码。




    _cdecl:CC++的缺省调用协议,由调用者清理堆栈。这就是CC++中能够使用可变參数的函数的原因。全部參数自右至作入栈,生成的代码中函数名有一个_做前缀.


    至此算是明确过来了,一般dll中的函数都採用extern "C" __stdcall的方式引出函数接口的,在调用DLL中的函数时,假设没有加__stdcall和__cdecall是缺省调用了__cdecall,而__cdecall是要由调用者清理堆栈的。而在代码中并没有清理堆栈的操作,仅仅是调用了函数,所以调


    用函数的地址可能会跑飞。

    不跑飞就OK。而一旦跑飞就出现Access violation的异常。而_stdcall是由被调用的函数清理堆栈,所以调用函数的地址不会跑飞,自然也就OK了。


    详细__stdcall/__cdecal/__fastcall的差别能够參见http://blog.csdn.net/limenglandon/article/details/8553201。  

  • 相关阅读:
    聊聊算法——回溯算法
    Redis高级用法
    聊聊算法——BFS和DFS
    这就是Java代码生成器的制作流程
    Spring Boot 2 实战:常用读取配置的方式
    Spring Security 实战干货:图解Spring Security中的Servlet过滤器体系
    想做时间管理大师?你可以试试Mybatis Plus代码生成器
    Maven中央仓库正式成为Oracle官方JDBC驱动程序组件分发中心
    作为一个Java开发你用过Jib吗
    使用反应式关系数据库连接规范R2DBC操作MySQL数据库
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/6912629.html
Copyright © 2020-2023  润新知