我有一个针对x86的旧库。我需要迁移它以使用x64。但是存在一些指针地址问题。当我为x64编译时,我丢失了指针地址。例如:
int main()
{
struct MY_STRUCT *p;
p = (struct MY_STRUCT *)malloc(sizeof(struct MY_STRUCT ));
int hnd = (int)p; //at this point, it tries to assign 64 bit address to a 32 bit variable. So half of the address is gone.
int ret;
ret=someFunct(hnd);
}
int someFunct(int p)
{
struct MY_STRUCT *p;
p = (struct MY_STRUCT *)(Handle); //at this point, p pointer takes an address value like 0x0000000012345678. And this causes access violation exception as expected.
return 0;
}
在GCC中,我记得可以使用编译器选项将int变量大小更改为8bytes(64bit)。在MSVC中,我可以这样做吗?我可以将所有保存地址的变量更改为64位变量,但这是一个很大的库,因此需要对其进行深入测试,以确保其与x86构建一样正常。任何建议将不胜感激。
在GCC中,我记得可以使用编译器选项将int变量的大小更改为8bytes(64bit)。
如果可能,最好不要这样做,其他代码/库可能不希望这样做。对于您的标头尤其如此,您不应该强迫库的使用者依赖编译器标志。
我可以将所有保存地址的变量更改为64位变量,但这是一个很大的库,因此需要对其进行深入测试,以确保其与x86版本一样正常。
如果写错了,这只是您要处理的事情。还有很多其他陷阱,直到不幸的一天,很多意外的内存覆盖和截断都会被忽略。
C和C ++具有typedef,可用于控制特定于平台的方面,以及使意图明确(例如,我知道从uintptr_t
获得的期望,而且我什至不希望long long
成为指针)。
请确保您已打开所有警告,并且我发现对Windows / MSVC和Linux / GCC进行检查可以发现一些东西,因为警告略有不同。例如:
int y = (int)ptr;
警告C4311:'类型转换':指针从'int *'到'int'的截断
Firstly never将指针转换为任何int类型,int
,long
,unsigned
等。在需要执行此操作的地方,有uintptr_t
和intptr_t
将具有正确的大小,其他库/ API在使用该API时可能会使用它们自己的类型(例如, Windows),这将有助于您支持它们正确运行的所有平台。
此外,由于没有完美的选择,因此您使用的其他库和API可能完全需要其他功能,例如Windows API LONG_PTR
无法处理64位的指针大小的值,无论您使用的是哪种typedef,但Microsoft都添加了可以适合指针的SetWindowLong
函数。
SetWindowLongPtr
取决于您的需要,这里有两个可能的选项: