[英]Exception thrown at 0x00000000 in Project0_opengl.exe: 0xC0000005: Access violation executing location 0x00000000
[英]Why do I get an Exception Exception thrown at 0x00000000 in ConsoleApplication1.exe: 0xC0000005: Access violation executing location 0x00000000
我正在尝试创建一个非常简单的 dll 并将其加载到另一个文件以供学习。 我对 DLL 和 C++ 文件使用相同版本的 VC++。 这是我的源代码:
加载.cpp:
#include <iostream>
#include <windows.h>
using namespace std;
typedef int(__stdcall* nsum)(int a, int b);
int main(void)
{
HINSTANCE myDll = LoadLibrary(L".\\DLL1.dll");
nsum sum = (nsum)GetProcAddress(myDll, "sum");
if (!myDll) {
cout << "could not load the dynamic library" << endl;
return EXIT_FAILURE;
}
int xfinal = sum(10, 20);
cout << xfinal << endl;
return 0;
}
和 dll.cpp
#include <windows.h>
#include "pch.h"
using namespace std;
int __declspec(dllexport) __stdcall sum(int a, int b)
{
return a + b;
}
pch.h
// pch.cpp: source file corresponding to the pre-compiled header
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
但我仍然得到了例外。 我搜索了答案,但没有找到,所以我写这个寻求帮助
在 load.cpp 中,在 HINSTANCE myDll 中,我可以窥视并看到设置为 0x000000000 的值。 是这个原因吗? 如果是这样,我该如何解决?
你的问题很简单。 您的 function 的导出名称不是sum
,因为您没有使用 C ABI 。 相反,它是一个错位的名称?sum@@YGHHH@Z
您使用GetProcAddress(myDLL, "sum");
时当然找不到它。 没有这样的 function sum 。 因此,您正试图在地址 0 处调用 function,即异常告诉您的内容。
Microsoft 将这些装饰名称称为“修饰名称”而不是“损坏的”,但它们的含义相同:参数类型、调用约定和返回值的类型信息被编码为构成名称的特殊符号。
这里有几个选项可以解决这个问题:
使用导入库而不是显式链接,这将使用损坏的名称,因此您可以坚持使用 C++ ABI。
通过extern "C"
使用 C ABI,保持现有的__stdcall
调用约定,在这种情况下,为 x86(32 位)构建时,名称将为_sum@8
:
extern "C" int __declspec(dllexport) __stdcall sum(int a, int b)
extern "C"
的 C ABI,但使用__cdecl
这实际上会导致 x86(32 位)的sum
:extern "C" int __declspec(dllexport) __cdecl sum(int a, int b)
对于 x64,有一个标准的调用约定__fastcall
( __cdecl
, __stdcall
只是__fastcall
的别名)。 在那里,仅使用extern "C"
将导致任何这些调用约定的名称sum
。 使用 x64 的 C ABI 导致“损坏”导出的唯一情况是extern "C" __vectorcall
。
如果您更改它,请务必更新您的 typedef 以匹配您正在使用的调用约定。
其次,您应该添加更多错误检查:
HMODULE myDll = LoadLibrary(L".\\DLL1.dll");
if (!myDll) {
cout << "could not load the dynamic library" << endl;
return EXIT_FAILURE;
}
nsum sum = (nsum)GetProcAddress(myDll, "sum");
if (!sum) {
cout << "could not find the export" << endl;
return EXIT_FAILURE;
}
如果您使用 C++11 或更高版本(Visual Studio 2012 或更高版本),则
auto sum = reinterpret_cast<nsum>(reinterpret_cast<void*>(GetProcAddress(myDll, "sum")));
更好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.