x64位windows上程序开发的注意事项
在Windows上面32位与64位的区别有:
1.指针大小的区别,sizeof(int *)在32bit下面是4个字节,在64bit下面是8个字节
2.size_t的区别,size_t在32bit下面是4个字节的范围,在64bit下面是8个字节的范围
3.地址空间的区别,在32bit下面,最大地址空间是4GB,在64bit下面是可以大于4GB的
4.32位程序在64位Windows上运行,是有一个Wow64子系统辅助其运行的,默认情况下,访问注册表和某些文件夹是被重定向的
5.指针的区别也意味着Handle的区别
6.唯一支持Windows原始64位编译的msvc编译器不支持64bit的内联汇编,如果要用汇编,需要单独编译再link
7.纯64bit程序的函数调用方式已经不再区分cdecl和stdcall方式,因为只有一种了。
8.64bit的程序不再使用esp,而是使用增加的几个64bit寄存器,因为esp不支持64bit空间的栈
最近的工作涉及到Linux的64位工作,发现当初对32位和64位区别的认识还不够:
1.long在Windows下面,不管是32bit还是64bit下,都是4个字节的,但在Linux下面,32bit下是4字节,在64bit下是8个字节。(long long在64bit下还是8个字节)
2.gcc在64bit下面,不再支持__attribute((cdecl))__和__attribute((stdcall))__,这点和Windows有点类似,开始以为是gcc的高版本不支持的,后来发现区别在x86和x64
64位下windows的开发建议:
1.避免System.BadImageFormatException
通常,程序员碰到这种情况:“出现未处理的类型异常 ‘System.BadImageFormatException’”。如果你要深究该异常的细节信息,可能会发现系统提示:“试图加载的程序,格式不正确”。
之所以会出现这样的问题是因为64位进程试图加载一个32位组件。虽然你在Windows x64上可以运行64位和32位进程,但是64位代码和32位代码不能在相同进程上运行。你的代码要么全部是64位,要么全部是32位。要加载的组件也要符合这一规律。
VS 2005与.NET 2.0为编译.NET应用程序带来选择,将输入设置为“Any CPU”也具备了可选性。“Any CPU”是默认平台。如果组件以Any CPU作为平台进行编译,那么它将依据进程加载的情况以32位或64位方式运行。使用Any CPU,相同的组件可以在64位Windows上以32位或64位方式运行:它不是真正的指定了64位的CPU或操作系统,而是一个调用进程。
为了解决不合格图像异常的问题,要改变到Any CPU的所有组件的目标平台。如果出于某种原因你无法做到这一点——或许某组件无法提供来源——那么要将所有组件设置成到达同一平台,可以是x86也可以 是x64。如果你拥有.NET 1.0或1.1组件,最好是用.NET 2.0对其重新进行编译。如果你不能编译.NET 1.0或1.1组件,那么编译其他代码,设置为到达x86平台,使之兼容。
2.大小问题
64位和32位Windows之间一个重要的区别是句柄的大小。如果你的代码中具备任意Windows API调用,那么你要确保你的说明对于64位Windows是正确的。如果代码是从VB6升级而来,那么你不能区分句柄和32位整数的概念,因此你必须寻 找源文件或标头文件。识别哪些参数和域是句柄,使用这些类型的IntPtr。通常情况下,文件将以INT_PTR或LONG_PTR将其识别或者用名称只 是某类句柄,如HWND。用前缀定义的参数,如PTR或LPTR通常是一些指示器,因此需被视为IntPtr或使用ByRef编组。要确定你运行的64位 还是32位,可以在运行时检查IntPtr.Size的值。
3.COM可以是64位
普遍存在的误解是认为COM和ActiveX仅限于32位,但是使用VB.NET,你可以使用64位COM和ActiveX控件。 Windows没有按照64位编译的控件,但是其中一个值得注意的例外是sysmon.ocx ActiveX 控件,该控件可以让你创建系统监测图。
你可以使用Windows.Forms应用程序中的64位ActiveX控件,但是当涉及汇编的时候就存在缓冲。VS当前是32位的应用程序, 它在汇编的时候需要32位的ActiveX控件以便创建运行时可随时启用的COM组件包装。为了在VS中进行编译,你需要32位的版本。一旦程序被编译, 就只需要被选中的平台。
在你没有32位版本或类似版本的情况下,你可以使用命令行来运行64位工具以便创建一个用于ActiveX控件的Interop程序集。见Tlblmp.exe文件以了解详情。
4.意识到问题
32位应用程序运行于Windows 64中时,它与模拟器一起运行。模拟器被称为WOW64,是Windows On Windows64的缩写,可以让32位应用程序按照32位操作系统进行查看。WOW64模拟器加载了一个ntdll.dll的x86版本,提供了切入点 和替换程序,还会截取最重要的注册表和文件系统操作。
WOW64模拟器也暴露出不同的适合32位应用程序的环境型变量。因此,32位应用程序将ProgramFiles环境型变量为 ProgramFiles(x86)。以64位运行的时候,如果你写出类似MsgBox(Environ(“ProgramFiles”))的代码,会获 得"C:\Program Files",如果你32位运行,则获得"C:\Program Files (x86)"。
模拟器所做的事情与注册表和系统目录类似。出于兼容性和性能的考虑,%windir%\System32 文件夹是64位文件夹。也就是说,64位应用程序中不存在任何截取。重新定向的32位操作文件夹默认名为%windir%\SysWOW64。名称 SysWOW64指明它要被32位模拟器WOW64使用。这或许有些令人困惑。
WOW64之下的注册表将重定向与反射结合使用。重定向存在于HKEY_LOCAL_MACHINE\SOFTWARE \Wow6432Node等Key之下。至少注册表中的命名式样更好。映射是32位进程和64位进程都可以编辑共同Key,如文件关联。另一方面讲,重定 向是为了确保将32位从64位隔离开。
关键是执行不能影响你除非你打算从64位程序中获取32位程序的详细信息,反之亦然。通常汇编到同一目标要简单得多。例如,如果你想使用VS, 将程序锁定到x86,你不需要担心文件或注册表的模拟过程。如果你要以Any CPU运行程序,那么就取决于它是如何启动的,或许你要使用重定向,和类似GetSystemWow64Directory的API调用,并且使用 RegOpenKeyEx API,包括KEY_WOW64_32KEY的访问假象。它可能变成混乱而复杂的测试。这是目前为止对相同平台和锁定信息最好的汇编方式。
其中笔者偶然发现的一个问题是注册表反射和Windows Vista UAC的结合。在用于写入许可的HKLM蜂巢中笔者开放了一个Key,API成功了,但是当笔者向Key写入时,却失败了。应用程序以32位方式运行于 Windows 64上,因此有问题的Key会被映射。笔者浪费了大量时间用于确定所发生的事情,因为注册表API不会向往常一样运作。最后,笔者通过往应用程序中包含运 载单使之正常运行。即便requestedExecutionLevel对asInvoker有级别设置,这一漏洞也可以被修复。
UAC提供了注册表虚拟化,笔者认为WOW64重定向或反射与UAC虚拟化的结合太多了。现在笔者通常会确保应用程序中具备运载单。在VS 2008中,你可以从项目属性对话框中的程序标签中获取运载单。确保你包含了requestedExecutionLevel选项。
5.激活Edit和Continue
虽然,你可以调试64位应用程序,那么就不能在调试期间使用Edit和Continue。这意味着你不能在调试的时候改变源代码,相反你要停 止,应用更改,重新编译并启动调试。但是你可以用32位程序使用Edit和Continue,即便是在64位Windows上。这是另一种手动构建配置的 示例。
创建一个x86构建配置,并且在开发的时候使用这一配置,如此你就可以使用Edit和Continue。然后将配置切换称x64或Any CPU用于测试。
使用Windows 32或Windows 64不如VB 8或VB 9中那样难。使用VS并且构建配置,任务会变得简单。
x64位windows上程序开发的注意事项的更多相关文章
- 使 IIS 6.0 可以在 64 位 Windows 上运行 32 位应用程序 试图加载格式不正确的程序。
原文 使 IIS 6.0 可以在 64 位 Windows 上运行 32 位应用程序 试图加载格式不正确的程序. win7 64位操作系统上边运行IIS网站应用的时候,提示错误"试图加载格式 ...
- 64位windows上访问64位oracle 12c
64位windows上访问64位oracle 12c,这会有啥问题? 没啥问题.问题是,我64位操作系统的机器上装了个oracle 10g.而oracle 10g好像是不区分啥32位.64位的,一律3 ...
- Windows上python开发--2安装django框架
Windows上python开发--2安装django框架 分类: 服务器后台开发2014-05-17 21:22 2310人阅读 评论(2) 收藏 举报 python django 上一篇文章中讲了 ...
- Go 程序开发的注意事项
Go 程序开发的注意事项 1) Go 源文件以 "go" 为扩展名. 2) Go 应用程序的执行入口是 main()函数. 这个是和其它编程语言(比如 java/c) ...
- Windows上Ruby开发环境的配置
最近公司项目上有需要,需要开发一个puppet的自动化工具,这个工具需要操作存储设备上的各种资源,而鉴于puppet不是善于完成这个任务的首选语言,于是我们选择了puppet的“爹”,Ruby. 熟悉 ...
- windows上node开发注意事项
windows上进行node.react开发的必要步骤: 1.使用nvm进行node及npm包管理工具,记得使用npm config set ...:2.另外react仅支持python3.0以下的版 ...
- windows上JSP开发环境全搭建
JSP开发环境全搭建 最近需要用到JSP做项目,所以要配置JSP的开发环境,总结一下配置步骤以备以后再配置需要. 配置JAVA开发环境,配置JDK 下载JDK,在这里下载开发所需的JDK,可以根据自己 ...
- Linux/Windows 应用程序开发
一.基础知识 虽然写的都是代码,但是代码运行在哪个级别什么位置,还是需要做好定位,这样才心中有数. 1.1 Linux [转载]讲述了中断.系统调用.Linux APIs和Shell的基本知识. 1 ...
- x64位windows 2003 server中“Server 对象 错误 'ASP 0177 : 800700c1' Server.CreateObject 失败”问题
给朋友看一个老asp网站图片不能上传问题,试过网上各种办法都提示: Server 对象 错误 'ASP 0177 : 800700c1' Server.CreateObject 失败 最终问题出在x6 ...
随机推荐
- Xcode编译项目出现访问private key提示框
原因: 在编译时Xcode进行codesign时需要访问"private key"时没有权限,然后让询问是否允许,有三个选项,全部允许.否绝.允许,一次弹出4个(我遇到的) 遇到问 ...
- 为什么我们不喜欢用富UI控件
我们对于理解一般意义的抽象关系并没有问题,但如第一部分使用Entity Framework 时说明的,事实恰好相反.我们还喜欢在交付应用程序时利用抽象关系,比如使用Azure等云服务.在这两种情况下, ...
- H5相关
对于容器元素,尤其在做移动端产品时候,我们很自然会让其居中定位: .container { position: absolute; left: %; top: %; transform: transl ...
- php实现返回上一页的功能的3种有效方法
php实现返回上一页的功能的3种有效方法 header(location:你的上一页的路径); // 注意这个函数前不能有输出 header(location:.getenv("HT ...
- PHP面向对象(OOP):克隆对象__clone()方法
有的时候我们需要在一个项目里面,使用两个或多个一样的对象,如果你使用“new”关键字重新创建对象的话,再赋值上相同的属性,这样做比较烦琐而且也容易出错,所以要根据一个对象完全克隆出一个一模一样的对象, ...
- 认识Web和HTTP
一:了解Web. 首先,Web应用的产生起源于1989年,当时CERN(欧洲核子研究组织)的蒂姆·伯纳斯-李(Time BernersLee)博士提出了一种能让远隔两地的研究者们共享知识的设想.借 ...
- Apache虚拟站点配置
简单虚拟站点配置: <VirtualHost 127.0.0.2:80> DocumentRoot E:/wamp/www/yue ServerName 127.0.0.2:80</ ...
- ZABBIX安装官方指南
慢慢,把这块业务要玩熟悉~~~~事前,事中,事后,它都能发挥自己的一些作用. From Zabbix official repository Zabbix SIA provides official ...
- Winform 隐藏程序窗口
internal class HideOnStartupApplicationContext : ApplicationContext { private Form mainFormInternal; ...
- 【转】java中float与byte[]的互转 -- 不错
原文网址:http://tjmljw.iteye.com/blog/1767716 起因:想把一个float[]转换成内存数据,查了一下,下面两个方法可以将float转成byte[]. 方法一 imp ...