编译一个只依赖于kernel32.dll和user32.dll的C ++程序?

时间:2011-01-24 19:33:12

标签: c++ windows visual-c++ runtime

我正在使用Visual Studio 2005。

我想编译一个简单的程序,该程序可以与任何Windows 32位版本一起使用,而不依赖于安装的c ++运行时库版本。

此程序将调用GetModuleHandleGetProcAddress函数而不进行任何其他函数调用,然后在退出代码为函数地址时退出。

如何在没有任何c ++运行时库的情况下编译只依赖于kernel32.dll和user32.dll的C ++程序?

5 个答案:

答案 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)

您需要定义自己的入口点,而不是使用mainWinMain。你的入口点是一个不带参数的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是不存在的!)。

depends.exe program showing only one dynamic dependency, kernel32.dll

答案 3 :(得分:0)

检查微小的库。也是静态链接。

答案 4 :(得分:0)

你实际上并不需要User32.dll,唯一真正无法删除的是Kernel32.dll和Ntdll.dll - 这些是由PsCreateProcess注入你的进程空间的(即内核的一半内核)创造一个新的过程)。