我正在使用Visual Studio 2005。
我想编译一个简单的程序,该程序可以与任何Windows 32位版本一起使用,而不依赖于安装的c ++运行时库版本。
此程序将调用GetModuleHandle
和GetProcAddress
函数而不进行任何其他函数调用,然后在退出代码为函数地址时退出。
如何在没有任何c ++运行时库的情况下编译只依赖于kernel32.dll和user32.dll的C ++程序?
答案 0 :(得分:5)
在项目选项下设置/NODEFAULTLIB
。在较新版本的Visual C ++中,您还必须关闭堆栈溢出检查,因为这会导致编译器自动插入对库函数的调用。
编辑:如果您的意思是“在任何32位Windows版本上运行”,那么您还必须使用editbin
来更改PE标头中的子系统版本字段。否则,在使用VC ++ 2005链接器构建时,您将被限制在(IIRC)Windows 2000及更高版本中,而较新版本的VC ++甚至更糟(默认情况下需要XP)。 Windows 2000是5.0,除了Win9x之外,您还需要指定3.5或更低版本以允许所有版本的NT。
答案 1 :(得分:5)
您需要定义自己的入口点,而不是使用main
或WinMain
。你的入口点是一个不带参数的void函数。您必须使用/entry:funcName
为链接器指定其名称(其中funcName
将替换为您希望用作入口点的函数的任何名称。)
执行此操作时,您还必须将子系统指定给链接器,如/subsystem:console
中所示。它通常根据它找到的函数名称推导出子系统(即main
- > gt; console,WinMain
- > Windows),但是当你使用自己的入口点时,你必须指定明确地说。虽然您可能不经常这样做,但即使您没有指定自己的入口点,也可以显式指定子系统,因此(例如)您可以使用main
作为Windows子系统的入口点程序,或WinMain
作为控制台程序的入口点。
答案 2 :(得分:1)
我不确定为什么每个人都建议不要使用标准库。此方法假定您希望代码在Windows 2000或更高版本上运行,并且不介意失去对Win 9x的支持。您仍然可以使用C / C ++标准库 - 您可以在项目的C / C ++代码生成页面中使用/MT
选项,该页面将静态链接到标准库中。
然而,有两个注释,第一个来自我:拥有一个动态链接标准库的想法是它中的任何错误都将被Windows Update修补(理论上)。如果以静态方式链接库,则需要重新分发应用程序以修复标准库错误。所以不建议。
其次,来自compiler options上的MSDN文章:
警告不要混用静电和 动态版本的运行时 库。有多个副本 一个进程中的运行时库 会导致问题,因为静电 一份副本中的数据不与之共享 另一份。链接器会阻止 你从静态和 一个.exe文件中的动态版本, 但你仍然可以得到两个(或 更多)运行时的副本 库。例如,动态链接 库与静态链接 (非DLL)版本的运行时 库使用时可能会导致问题 与链接的.exe文件 动态(DLL)版本的 运行时库。 (你也应该 避免混合调试和非调试 一个版本的库 过程。)
简而言之,如果您尝试构建与动态链接的标准库链接的其他组件,这样做可能会造成混淆。
当然,另一个缺点是这会使你的可执行文件更大。
编辑:在depends.exe下的结果如下所示:(当然,我使用的是64位Windows,仅适用于XP及更高版本...如果你想知道这是什么样子在32位窗口上,想象一下64
是不存在的!)。
答案 3 :(得分:0)
检查微小的库。也是静态链接。
答案 4 :(得分:0)
你实际上并不需要User32.dll,唯一真正无法删除的是Kernel32.dll和Ntdll.dll - 这些是由PsCreateProcess注入你的进程空间的(即内核的一半内核)创造一个新的过程)。