vs2008_taotao

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

公司的一个产品需要转移到了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会更好吧? 
如此这样一个不错的技术可能慢慢被人们淡忘. 

引申一个问题就是我们现在硬件越来越好,但是大家还是觉得不够用,为什么? 

posted on 2010-08-19 13:11  vs2008_taotao  阅读(868)  评论(2编辑  收藏  举报