当前位置:   article > 正文

64位地址强转和解引用注意长度_合约交易64位转地址

合约交易64位转地址


在看C++对象模型相关的帖子,最常见的是直接拿对象的地址去取虚表地址,代码如下:

Base b;
printf("%p\n", (int*)*(int*)*(int*)(&b));
  • 1
  • 2

但是,这里的代码是在32位下的,如果是x64位就直接宕了

长度

原因是x64位的地址是64位的,而x86下面是32位的。

// x86下面的地址
0034116D
003412EE

// x64下面打印的地址
00007FF664371447
00007FF66437108C
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

出问题的地方主要是强转之后解引用发生的,在x64下面int指针还是64位的,强转没有问题。但是,如果(int*)之后就出问题了,拿到一个int类型的整数,只有32位。而后面又去把它转成int*的64位地址,高位用0xFFFFFFFF补全,结果就不对了。

0x00007FF6BB966841 处(位于 diffrent_address_study.exe 中)引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFBB96AD30 时发生访问冲突。
  • 1

开始以为把int换成long就行了,结果死翘翘,long也是4位。这个估计得看系统了,我得win10下面,x64下面的长度如下

sizeof(int) = 4
sizeof(long) = 4
sizeof(int*) = 8
sizeof(long*) = 8
sizeof(intptr_t) = 8
  • 1
  • 2
  • 3
  • 4
  • 5

解决

使用intptr_t代替

看定义

// Definitions of common types
#ifdef _WIN64
    typedef unsigned __int64 size_t;
    typedef __int64 ptrdiff_t;
    typedef __int64 intptr_t;
#else
    typedef unsigned int size_t;
    typedef int ptrdiff_t;
    typedef int intptr_t;
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

所以,这也提醒我自己,以后写代码地址转成int这样的操作很危险。用库里面有的类型,比如这里intptr_t。

跳过解引用运算符

还看到一些网友[1]的写法,我觉得这个比较好,跳过了解引用运算符的操作,也就不会出现问题了。而且对于虚表也比较清晰

Base b;
long** pVtab = (long**)&b;
  • 1
  • 2

参考

[1]C++对象在64位机器上的内存布局

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号