[英]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函數時訪問沖突異常是正確的答案,但是有點難以解釋-我看到的問題是:
檢查是向后的-如果我們未能獲得函數指針,則繼續進行,並且僅在成功獲得函數指針時才拋出。
由於成員函數是靜態的,因此應該很好地導出成員函數,但是由於DLL不會導出名為“ Add”的函數,因此我們無法獲得函數指針-實際名稱將被修飾並且可以在.map文件中找到(如果生成)。
由於找不到函數指針,因此我們將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.