会员登录 - 用户注册 - 网站地图 Office中国(office-cn.net),专业Office论坛
当前位置:主页 > 新闻 > 行业新闻 > 正文

程序64位化带来的问题和思考

时间:2006-10-21 00:00 来源:JAVAEYE 作者:Arath 阅读:
公司的一个产品需要转移到了Windows Vista 64上去,由于程序某一部分和Windows的一个AP紧密相连,而这个Windows AP已经64位化了,不得不将自己的程序也转到64位。

  我原来不是负责这个产品的,由于项目很赶,所以被零时抽调去帮忙,遇到了一些问题,这里和大家分享下。

  1. 指针和long的转换

  这是最基本的处理部分,由于32位系统下地址是32位,所以很多代码里都会存在这样的转换:

  void* pData;

  LONG lData;

  lData = (LONG)pData;

  现在地址是64位了,所以原来的这种转换就会导致地址高4Byte丢弃的问题。

  这种转换向来被认为不安全,但还是大量出现,实际程序员代码的时候只要用一个指针保留就可以,完全没有必要用一个long保留,同样的问题也会出现在函数指针的保留。

  思考:

  所谓的存在即合理的思维在作怪吧,很多程序员认为这么做程序运行的好好的,所以不管是否有风险还照样这么写,实际上改成安全写法代码多不了多少。

  当然不排除很多程序员对16位、32位、64位完全没有概念的。

  还有一点可能是微软的windows消息给人以误导,消息的WPARAM和LPARAM中常会夹带数据指针,然后强制类型转换,但是看一下它们的定义,其中隔了一层,虽然只是语法上的小小手脚,但是绝对是有先见之明, 而很多人只会依样画葫芦而未明白期间的巧妙。

  2. PE Import和Export Table的变化

  程序中用到了PE hack,由于之前有人发现vista 32下原来所需要替换的一个import table中的函数找不到了,结果竟然去修改了export table, 姑且不谈修改export table的危险吧,结果vista 64的时候发现PE格式有了小小的变更。

  MS将Import table中的地址转成了64bit,但是export table却还是32bit,估计其认为代码不可能大于4GB吧,这样就会发现更改export table变得很难,因为不同的dll会被load在不同的地址段,其间差距会大于4GB,所以只有将自己的dll强制定义在和目标dll相同的4GB范围内。

  回头来说这种更改是极其危险的,因为对于export table OS会尽量保持全局唯一,所以一旦你的dll退出未能正确恢复原有的值,会造成其他所有使用到这个dll的程序crash。

  最终我发现需要hack的那个函数放在了delayload import table中,简单的修改就解决了问题。

  如果这个问题最终找不到而还是采用修改export table的方法,那么就会很惨,测试部门已经发现了经常性的系统crash。

  思考:

  这里出现了弯路,这个弯路项目的时间压迫难辞其咎,但是程序员未能自己去分析问题是更大的问题,vista在很多方面都保留了很好的兼容性,去分析下windows的目录就会发现基本和xp区别不大,所以很多基础dll的功能也没有变化(这一点让我感觉到vista并未如其发表的那样70%代码重写),在分析dll的时候只要稍微仔细点就会找到问题很简单。

  另一个问题就是MS在定义PE格式的时候的确有很高的前瞻性,很好的保持了松耦合的能力,其实PE格式在2001年后就基本没有什么大的更改,那时大家还基本没有64位的概念,这一点是需要学习的,但是同样对于export table没有扩展到64bit我还是保留意见,难道真的认为4GB不会超过?当年盖茨大叔不是宣称640KB就够了吗?

  3. DelayLoad的问题

  DelayLoad这个特性在VC6开始出现,一般大家不会去接触,包括我自己,要不是这次机会也不会去看。

  推荐一篇文章

  http://www.microsoft.com/msj/0200/hood/hood0200.aspx

  有详细的阐述,有兴趣可以自己看一下,其实其原理很简单,主要是在使用到某个dll的接口的时候再去load这个dll,这样可以节约空间,因为有些dll中的接口可能在程序周期中永远不会用到, 而且如果某个dll没有,如果没有用到,那么整个程序也能继续执行。

  这真的是一个巧妙的设定, 虽然在第一次呼叫的时候会有小小的性能损失,并且代码也会稍微大一点,但是可能会带来更大的空间节省。

  但是随即带来的思考, 为什么这么好的一个东西会那么生疏呢?个人考虑有以下原因:

  1. 这种技术显然对于很多人来说过于底层了,有多少人在意编译出来的程序是怎么样存放,又是如何被加载运行的呢?

  2. DelayLoad带来的好处对很多人不可见,只要我的程序编译通过,并且可以正确执行就可以了,节省了那么些空间或者扩展兼容有必要考虑吗?

  3. 现在的硬件太好了,何必要去做这种优化呢?内存消耗多了,没什么嘛去买1GB内存插上不久解决了?

  4. 编译系统不够智能,可能Visual Studio做的更加智能些,自动去分析然后产生delay load会更好吧?

  如此这样一个不错的技术可能慢慢被人们淡忘。

  引申一个问题就是我们现在硬件越来越好,但是大家还是觉得不够用,为什么?这几天我在写另一篇文章,可惜一直很忙还未能完成,就是自己在反思分析这个问题.

(责任编辑:admin)

顶一下
(0)
0%
踩一下
(0)
0%
推荐内容
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价: