在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
delphi XE2新增对64位程序的支持,从框架到编译器都相当成熟,不过由于原有代码都是针对32位,在重新编译成64位,或者在编写64位程序时,由于32位代码的编写习惯,有时会出现一些莫名奇妙的问题。 如最近在编写password filter的时候,发现同样的源码编译到32位可以正常工作,但编译成64位就出现的异常,最后发现是在实现其中PasswordFilter和PasswordChangeNotify时其参数为UNICODE_STRING的问题, 在访问Buffer字段时内存非法访问异常,该结构定义如下: _UNICODE_STRING=PACKED RECORD 在32位系统中,CPU寻址按4字节对齐,该结构内存结构 PACKED后其实与没有PACKED是一样的, 首先认识到寻址的对齐目的,是为了避免CPU访问数据时由于数据跨边界而需要2次寻址的问题,而32位单次寻址大小是4字节, Length加上MaximumLength 的大小只有4字节,刚好可以将该2字段存放同一边界内, 在访问Length和MaximumLength时实际都分别只需要寻址一次, Buffer也是寻址一次, 也就是说这里即使使用PACKED ,CPU访问所有字段的寻址次数也没有变化,因此PACKED后与没有PACKED大小是一样的。
但是在64位系统,这里就出现差别了,因为64位的CPU寻址是按照8字节对齐的,由于Length加上MaximumLength 的大小只有4字节,可以存放在同一边界内,这时该边界内仍然剩余4字节, 结构使用PACKED后,将导致 Buffer紧跟着存放在剩余的4字节中,而Buffer为8字节的指针,因此还有4字节需要存放到下一个边界,也就是 Buffer 数据存跨越两个寻址边界,结果CPU要取得 Buffer数据就需要寻址2次。 微软的64位系统通常不会出现这种存在跨边界字段的结构体,因为会增加寻址次数导致速度降低,因此他们在64位系统中对该结构进行修补,如下: _UNICODE_STRING=PACKED RECORD 这样一来,Buffer会被“挤到”下一边界,CPU只需寻址一次就够了,与32位的结构寻址次数相等,经过该结构体的修改,再编译成64位的 password filter就可以正常工作了。 以上可以看出,32位的源码要编译出正确的64位程序,通常需要修改各种系统结构体的定义。
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论