64位程序崩溃-访问越界
事件起因
最近在做一个32位程序编译成64位的工作,遇到一个很奇葩的问题,程序在32位下运行非常正常,可编译64位以后总是莫名崩溃,崩溃的的报错是这样的。
经过分析发现原来是以前的代码用DWORD来存储指针导致的地址越界错误。
现场模拟
先看一段代码
#include <stdio.h>
#include <windows.h>
void func_a(){
printf("func_a output");
}
typedef void funca();
int main()
{
DWORD ptr_func_a = (DWORD)&func_a;
printf("%p\n",&func_a);
funca* p_func=(funca*)ptr_func_a;
printf("%p\n", p_func);
p_func();
return 0;
}
这段代码在32位下能正常运行,改成64位就会出现越界异常
32位运行截图

原因分析
DWORD不论在32位还是64位下都是4字节32位长,因此在64位下保存函数地址的时候就会发生截断,只保存了前32位,后32地址丢失了,进而访问函数地址的时候就会出现一个不存在的地址。

从打印的地址可以看出函数地址的高位已经丢失了
如何避免这种问题发生
不要用DWORD存储指针,可以改用DWORD_PTR,DWORD_PTR定义的时候针对64位和32位分别做了不同的定义
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
//...省略一万字
#if defined(_WIN64)
typedef __int64 INT_PTR, *PINT_PTR;
typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
typedef __int64 LONG_PTR, *PLONG_PTR;
typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
#define __int3264 __int64
#else
typedef _W64 int INT_PTR, *PINT_PTR;
typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;
typedef _W64 long LONG_PTR, *PLONG_PTR;
typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
#define __int3264 __int32
#endif
修改后的运行结果


浙公网安备 33010602011771号