調用DLL函數,出現錯誤
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
錯誤原因:
你定義函數指針原型時出錯。
其實你定義的沒有錯,但是編譯器不認識而已,因為你調用的dll函數是一個遠函數,而且是一個C函數,你得告訴編譯器它是個c函數才行。那么你就可以在定義該函數的時候加上一句話,
FAR PASCAL 或者 __stdcall 這個就OK了。
具體做法:
比如說你要定義一個 返回類型為空,參數為空的函數指針:
typedef void (*LPFUN)(void);
這樣確實跟我們dll里的函數匹配了,上面也說了,我們應該添上幾個字,告訴編譯器這個是一個遠的C函數。
typedef void (WINAPI *LPFUN)(void);
typedef void (__stdcall *LPFUN)(void);
typedef void (FAR PASCAL *LPFUN) (void);
像上面這樣定義就OK了,如果用的是VC++,那么直接用第一種定義就ok了。
注意,上面是使用 MFC (DLL)的做法。
如果是WIN32 DLL,得相應的去掉WINAPI ,__stdcall ,FAR PASCAL 這幾個參數。因為WIN32 DLL 默認的入棧方式為 __cedcall方式,不是__stdcall方式。
具體的組合方式太多了,反正知道錯誤的原因是聲明相應的函數未匹配就行了。
調用DLL里的函數 或 類成員函數 碰到此錯誤:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
函數定義的調用規則,和實際的調用規則不同。如 編譯器默認的是__cdecl,而__stdcall 類型的函數卻用了 __cdecl 的調用規則,由於編譯時不會報錯,結果出現了運行時異常。
所以把在函數定義中進行設置調用規則即可解決此問題。
如: typedef void (__stdcall Foo)(int a);
很久沒寫代碼,一天幾行的代碼:
typedef int ( *PFUN)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
void CTestProcessMonitorDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
//MessageBox(TEXT("Hello"), TEXT("Test"));
//typedef void (*pfv) ();
HMODULE hmod = ::LoadLibraryExW(TEXT("user32.dll"), NULL, 0);
if (hmod != NULL)
{
PFUN pFun= (PFUN)GetProcAddress(hmod, "MessageBoxW");
if (pFun != NULL)
{
pFun(m_hWnd, TEXT("Hello"), TEXT("Test"), MB_YESNO);
}
:FreeLibrary(hmod);
}
}
突然出現以下的錯誤:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
代碼改為如下, 則問題沒有了
typedef int (WINAPI *PFUN)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
void CTestProcessMonitorDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
//MessageBox(TEXT("Hello"), TEXT("Test"));
//typedef void (*pfv) ();
HMODULE hmod = ::LoadLibraryExW(TEXT("user32.dll"), NULL, 0);
if (hmod != NULL)
{
PFUN pFun= (PFUN)GetProcAddress(hmod, "MessageBoxW");
if (pFun != NULL)
{
pFun(m_hWnd, TEXT("Hello"), TEXT("Test"), MB_YESNO);
}
::FreeLibrary(hmod);
}
}