移植代码到64位平台
请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com
C和C++大量依赖于指针的使用,即包含内存地址的变量。尽管指针类型在概念上与整数类型不同,但其物理地址值 始终是一个整数 。开发人员在C/C ++中大量使用整数类型而不是指针类型,即使在编译器随附的系统头文件中也是如此。在过去的几十年中,大多数计算机处理器都使用32位内存地址,因此开发环境是 围绕地址长度为32位的假设 建立的。C/C++代码中存在着大量 指针和整数之间的隐式和显式转换 。使用指针,或union的重叠内存结构方式(overlapping memory structures),去访问变量,也是司空见惯。
当然,32位架构有其局限性。具体来说,它们将计算机内存限制为4GB。应用程序需求不断增长,迫切需要迁移到更长的地址。经常使用的旧式类型带来了新的含义和价值。最具戏剧性,最明显的的变化,是从32位转向64位指针。
不再适用相同的规则 基本类型的某些大小已更改。其中一些保持不变。但是,突然之间,在C和C++代码库中使用的许多隐式假设不再有效。在32位系统中编写和测试的代码在迁移到64位计算机时不再有效。
幸运的是,已经识别并分类了代码可能易于从32位计算机迁移到64位计算机的大多数区域。一些编译器使用主动检查技术来捕获在迁移期间可能出现的漏洞。静态分析工具的供应商(包括Coverity和Klocwork)可以提供进一步帮助将代码从32位机器平稳迁移到64位机器的机制。尽管这些工具不能直接解决代码迁移问题,但它们提供了便利的可扩展性和API,可以创建与32位到64位迁移相关的自定义检查程序。增强这些工具可以进一步帮助发现并有效解决这些兼容性问题。
本文的目的是帮助您使代码库与体系结构无关,因此可以在32位计算机或64位计算机上构建相同的代码库,并为每台计算机生成可行的代码。此外,如果32位程序通过二进制数据交换(通过文件或套接字)与64位程序进行通信,则有多种方法可以确保二进制结构不受两种体系结构类型之间的迁移的影响。
本文包含详细的分析和建议,以解决与32位到64位迁移有关的众多问题。
为了使您的程序与体系结构无关,有两个目标需要实现。 其中之一是内部一致性,即确保程序中使用的所有类型都是一致的,而不管代码是在32位还是64位计算机上编译的。 让我们看一下两种架构上基本类型的大小(请参见表1)。
此处的显着区别是指针类型和long类型的大小变化。由于大小更改,某些基于隐式依赖关系构建的代码可能无法正确迁移。可能的问题主要与整数与整数之间,或者是整数和指针之间的数据交换有关。
整数大小的差异 在32位系统上,int和long类型都是32位,这意味着程序员可以互换使用这两种类型。此外,C没有严格的输入规则,因此函数中的int参数可以传递long参数而不会出错。尽管这不是一个好的编码实践,但是此代码可能会在数年内完美运行。但是,在64位系统中,在某些编译器中,int和long具有不同的大小,并且代码在迁移后将无法正常工作。将long值分配给int变量可能会导致截断。以下代码在32位系统中可以正常工作,但在64位系统中则极有可能正常工作。
int sum; long val1, val2; sum = val1 + val2; // possible truncation in 64-bit system 以下代码可能会在某些编译器中引起编译器警告,但是此代码(在32位模式下工作)可能将无法在64位模式下工作,因为堆栈上的值大小会发生变化。
int add(int parm1, int parm2); // ..... long val1, val2; long sum = add(val1,val2); // mismatch of parm size on 64-bit machine 可能还会发生其他一些细微的事情,从而影响代码的完整性。例如,编译时函数sizeof()返回类型为size_t的结果,size_t类型的占据的字节大小,则取决于该程序中指针类型变量占据的字节数的大小。将此值分配给整数可能导致被截断。如下代码所示:
int mySize = sizeof(MyStructure); // possible size truncation 另一个更细微的错误是位字段的符号扩展。 例如: