DLL 调用约定和访问冲突
DLL calling conventions & access violation
在这个伟大的平台上阅读和学习了多年后,这是我现在的第一个帖子。
我的问题:
在c++中,我试图创建一个动态链接库(32位),它将作为AQMP通信客户端(基于SimpleAmqpClient)。dll文件将在第三方应用程序(32位)中使用。
在我的测试中,我在自定义可执行文件中调用dll,一切工作正常。但是,当我尝试在第三方应用程序中使用dll时,我得到访问违反错误(0x00000000)。我发现问题可能是函数调用约定。
使用下面提供的几行代码可以重现错误。如果我在mytest.dll中删除 __stdcall
表达式,它就会消失。通常我希望代码能够工作,因为它在custom_test.exe和mytest.dll中使用相同的调用约定。(旁注:第三方应用程序期望__stdcall
功能,这就是我依赖它的原因)
我想了解这种行为。提前感谢!
我设置:- 操作系统:Windows 7
- 编译器:gcc 5.3 (Cygwin)
我的代码(custom_test.exe):
#include <stdio.h>
#include <windows.h>
int main(void) {
HINSTANCE hInstance;
hInstance=LoadLibrary("mytest.dll");
FARPROC lpfnGetProcessID = GetProcAddress(HMODULE(hInstance), "test");
// Function prototype
typedef void (__stdcall *myFunction)(void);
myFunction test;
test = myFunction(lpfnGetProcessID);
// Call Function
test();
FreeLibrary(hInstance);
}
我的代码(mytest.dll):
extern "C" __declspec(dllexport) void __stdcall test(void) {
printf("Inside Function n");
}
我通过
编译代码- dll:
g++ mytest.cpp -o mytest.dll -shared -std=gnu++11
- exe:
g++ custom_test.cpp -o custom_test.exe -std=gnu++11
__stdcall约定使被调用函数负责在返回时清理堆栈,而__cdecl使其由调用方负责。
我们无法在第三方DLL中看到实际的声明,但我最初的假设是DLL期望参数,并且要么使用它认为是错误的堆栈参数,要么根据它对堆栈参数的假设清理堆栈,并且通常会弄乱您的堆栈。
编辑在这种情况下,我看到在32位编译时,测试函数以'test@0'的名称导出。如果你改变你的GetProcAddress使用这个修饰的名称,它将工作
好了,现在几个小时后我又能看清楚了!谢谢IanM_Matrix1的建议,所谓的名称装饰确实是关键。
经过我的研究,我现在可以分享一些有用的资源,我发现:重要的是要知道,一些编译器会给函数名添加不同的修饰,参见这里:http://wyw.dcweb.cn/stdcall.htm
考虑到这一点,我们可以阅读这一页关于Win32调用约定的一般内容:http://www.unixwiz.net/techtips/win32-callconv.html当使用gcc时,装饰物也可以通过标记-Wl,--kill-at
来禁用。
- 写入位置0x0000000C时发生访问冲突
- 引发异常:读取访问冲突**dynamicArray**为0x1118235.发生
- 链表中写入访问冲突的未知原因
- C++中的openCV Mat访问冲突
- C++尝试深度复制唯一指针时出现内存访问冲突
- C++ 中动态二维数组的访问冲突
- 从嵌套循环中的 std::list 中删除将返回访问冲突
- 写入访问冲突异常
- 在类 12.exe 中0x7B37FF80 (ucrtbased.dll) 引发异常: 0xC0000005:访问冲突读
- 0xC0000005:访问冲突写入位置0xCDCDCDCD动态分配错误
- 读取访问冲突.这0xCDCDCDCD
- 0xC0000005:访问冲突读取位置 0x00000000. 重载 == 运算符的问题
- 插入数组时违反写访问冲突
- 使用 ReadProcessMemory 获取字符串值的访问冲突
- 尝试通过共享指针使用变量时读取访问冲突
- 堆栈上的 C++ 访问冲突写入异常
- 引发异常:写访问冲突. temp 为 nullptr
- 将静态字符数组中的字符分配给动态分配的字符数组 - 访问冲突
- 在C++中删除双向链表的头节点后出现访问冲突异常
- DLL 调用约定和访问冲突