X64平台越来越普及,目前一些分析软件多推出了X64版本,而我们的工具集项目同样也有X64版本。我们基于同一套标准C++代码实现了Windows和Linux的跨平台,这几天从X86平台向X64平台迁移的过程中,却遇到了一点麻烦,也学到了一招:(以下内容均限定在wintel+vc 10.0编译器)
假如我有一个类ClassA
class ClassA { ... public: int search(Filter, void**); ... };
ClassA的1个查询方法(例如空间查询)search接收一个查询过滤器,返回void*数组,在search函数的实现中,采用下面语句:
malloc(sizeof(void*)*count);
好,接下来考虑如下两种调用情形:
long* r_lst1 = NULL; void* r_lst2 = NULL; int r1 = ClassAObj->search(flt, r_lst1); int r2 = ClassAObj->search(flt, r_lst2);
显然,不管什么平台,条件相同的查询得到的结果数量肯定是相同的,也就是有r1==r2;
且在32位平台下,r_lst1与r_lst2将不会有任何区别;
但是在x64平台下,r_lst1在外部显式地声明为long*类型,而long类型在32和64位下均占4个字节,但是在函数实现中采用void*类型申请内存,void*在32位下占4个字节,而在64位平台上占8个字节,这样在外部使用r_lst1[i]形式访问r_lst1中的元素时,就会带来错误。
反过来看第二次查询操作,x64平台下它在外部声明的void*本身为8字节长度,因此不会带来函数内外数据类型字节长度不一致的问题。
因此在这样的一些查询操作中,与其将对象的标识符(通常为整数)作为查询的预期结果元素放入索引结构中,自行在外部处理跨平台问题,不如直接将所操作的对象指针放入索引结构,这样采用void*来进行操作,就避免了数据类型转换带来的字节长度不一致的问题,同时在内存中操作数据也更加便捷,省去了查询到标识符再去取对象数据的过程,可通过直接cast来获得要操作的对象,缺点是查询过程中对象占用内存。
在GIS中需要跨平台(特别是x86+x64)的空间查询优化过程中可考虑该技巧。