簡體   English   中英

使用DLL函數時的訪問沖突異常

[英]Access violation exception when using a DLL function

我在C ++練習中創建了一個簡單的DLL,但是調用DLL函數時卻遇到訪問沖突異常。 這是DLL的頭文件(我懷疑CPP在這里會有用):

#pragma once

namespace MathFuncs
{
class MyMathFuncs
{
public:
    // Returns a + b
    static __declspec(dllexport) double Add(double a, double b);

    // Returns a - b
    static __declspec(dllexport) double Subtract(double a, double b);

    // Returns a * b
    static __declspec(dllexport) double Multiply(double a, double b);

    // Returns a / b
    // Throws DivideByZeroException if b is 0
    static __declspec(dllexport) double Divide(double a, double b);
};
}

這是我的主要內容:

#include <iostream>
#include "windows.h"

using namespace std;

int main(void)
{
    double (__cdecl *MYPROC)(double,double);
    /* get handle to dll */
    HINSTANCE hGetProcIDDLL = LoadLibrary("DLLExample.dll"); 
if(hGetProcIDDLL == NULL)
    throw;
   /* get pointer to the function in the dll*/
    FARPROC lpfnGetProcessID = GetProcAddress(hGetProcIDDLL,"Add"); 
    if(lpfnGetProcessID)
        throw;
    MYPROC = (double (__cdecl *)(double,double))lpfnGetProcessID;
    if(MYPROC)
        throw;

    double x = MYPROC(5.5,5);

    return 0;
}

有什么建議么? 謝謝!

您的問題出在這里:

FARPROC lpfnGetProcessID = GetProcAddress(hGetProcIDDLL,"Add"); 
if(lpfnGetProcessID)  // <-- error!
    throw;
MYPROC = (double (__cdecl *)(double,double))lpfnGetProcessID;
if(MYPROC)  // <-- error!
    throw;

double x = MYPROC(5.5,5);

如果lpfnGetProcessId具有地址,則拋出異常。 如果不是,請稍后再調用它(轟!)。

您將要用extern "C"裝飾您的函數,以確保將它們導出為用戶友好的名稱。 這意味着他們不能進入課程:

namespace MathFuncs
{
   extern "C" __declspec(dllexport) double Add(double, double);
}

如果沒有DLL的代碼,則只能推測,並且您選擇的命名似乎會在中途發生變化,但看起來您正在執行以下操作:

1)加載dll,如果失敗則拋出異常...確定。 2)在dll中找到一個似乎將兩個值加在一起的函數-但是如果成功,則會拋出異常? 由於沒有引發異常,因此返回了NULL,因此無法找到該函數。 3)調用該函數-為NULL,因此您將在此處失敗。

我懷疑問題是您沒有考慮C ++名稱修改。 您可以更改對GetProcAddress()的調用中的函數名稱,以正確解決該問題,也可以使用extern "C"聲明該函數以刪除重整。

您確定方法MathFuncs::MyMathFuncs::Add()實際上是作為簡單的“添加”導出的,就像在GetProcAddress調用中一樣?

我懷疑涉及某種形式的C ++名稱修改

您可能想從命令行使用DUMPBIN / EXPORTS來查看實際的導出方法名稱。

此外,如果GetProcAddress的返回值不為 NULL (請參見if測試),則該函數成功:為什么throw

還請注意,如果您以這樣的方式調整類頭文件以在導出和導入中使用它,則使用DLL會更簡單:

#if defined(MATHFUNCS_EXPORT) // Inside DLL implementation
#define MATHFUNCS_API __declspec(dllexport)
#else   // Outside DLL
#define MATHFUNCS_API __declspec(dllimport)
#endif  // MATHFUNCS_EXPORT

class MyMathFuncs
{
public:

  static MATHFUNCS_API double Add(double a, double b);
  ...
};

這樣,客戶端可以#include您的頭文件(並與相應的.lib文件鏈接),而無需使用LoadLibrary / GetProcAddress

我認為使用DLL函數時訪問沖突異常是正確的答案,但是有點難以解釋-我看到的問題是:

  1. 檢查是向后的-如果我們未能獲得函數指針,則繼續進行,並且僅在成功獲得函數指針時才拋出。

  2. 由於成員函數是靜態的,因此應該很好地導出成員函數,但是由於DLL不會導出名為“ Add”的函數,因此我們無法獲得函數指針-實際名稱將被修飾並且可以在.map文件中找到(如果生成)。

  3. 由於找不到函數指針,因此我們將NULL強制轉換為函數指針類型並嘗試調用它,因此這就是我們遇到訪問沖突的地方。

代碼應為:

FARPROC lpfnGetProcessID = GetProcAddress(hGetProcIDDLL,"**MangledAddFunctionName - see .map file**");
if(lpfnGetProcessID == NULL)
    throw;
MYPROC = (double (__cdecl *)(double,double))lpfnGetProcessID;
if(MYPROC == NULL)
    throw;

double x = MYPROC(5.5,5);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM