_WinMainCRTStartup 执行什么功能?
这是一系列至少两个密切相关但又截然不同的问题的一部分。我希望通过单独询问他们来做正确的事情。
我正在尝试让我的 Visual C++ 2008 应用程序在没有 C 运行时库的情况下运行。它是一个 Win32 GUI 应用程序,没有 MFC 或其他花哨的东西,只是简单的 Windows API。
所以我设置了项目属性->配置-> C/C++->高级->将默认库名称省略为“是”(编译器标志 /Zl
)并重建。
然后链接器抱怨未解析的外部 _WinMainCRTStartup
。公平地说,我可以告诉链接器使用不同的入口点,例如 MyStartup
。根据我在网络上收集的信息,_WinMainCRTStartup
执行一些初始化操作,我可能希望 MyStartup
执行其中的一部分。
所以我的问题是:_WinMainCRTStartup
执行哪些功能,如果不使用 CRT,我可以省略哪些功能?
如果您对此了解东西,请看看 我的还有其他问题。谢谢!
旁白:为什么我首先要这样做?
- 我的应用程序没有明确使用任何 CRT 函数。
- 我喜欢精益且简单的应用程序。
- 它会教我一些新东西。
This is part of a series of at least two closely related, but distinct questions. I hope I'm doing the right thing by asking them separately.
I'm trying to get my Visual C++ 2008 app to work without the C Runtime Library. It's a Win32 GUI app without MFC or other fancy stuff, just plain Windows API.
So I set Project Properties -> Configuration -> C/C++ -> Advanced -> Omit Default Library Names to Yes (compiler flag /Zl
) and rebuilt.
Then the linker complains about an unresolved external _WinMainCRTStartup
. Fair enough, I can tell the linker to use a different entry point, say MyStartup
. From what I gather around the web, _WinMainCRTStartup
does some initialization stuff, and I probably want MyStartup
to do a subset of that.
So my question is: What functions does _WinMainCRTStartup
perform, and which of these can I omit if I don't use the CRT?
If you are knowledgeable about this stuff, please have a look at my other question too. Thanks!
Aside: Why do I want to do this in the first place?
- My app doesn't explicitly use any CRT functions.
- I like lean and mean apps.
- It'll teach me something new.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
发布评论
评论(3)
用 C(不是 C++)编写的 true Win32 程序根本不需要任何初始化,因此您可以使用 WinMainCRTStartup() 而不是 WinMain 来启动项目(实例,...)。
将控制台程序编写为真正的 Win32 应用程序也是可能的,但有点困难;入口点的默认名称是_mainCRTStartup()。
禁用所有额外的代码生成功能,如堆栈探测、数组检查等。仍然可以进行调试。
初始化
有时您需要第一个HINSTANCE参数。对于 Win32(Win32s 除外),它固定为 (HINSTANCE)0x400000。
nCmdShow 参数始终为SW_SHOWDEFAULT。
如有必要,请使用 GetCommandLine() 检索命令行。
终止
当您的程序生成线程时,例如通过调用GetOpenFileName(),从WinMainCRTStartup()返回带有return关键字将挂起您的程序 - 使用<改为强>ExitProcess()。
注意事项
在以下情况下您将遇到相当大的麻烦:
- 使用大于 4 KB(每个函数)的堆栈帧(即局部变量)
- 使用浮点算术(例如 float->int 转换)
- 在 32 位机器上使用 64 位整数( 使用 C++ new、delete进行乘法、位移操作)
- 的具有非清零所有成员构造函数的静态对象
- ,以及使用标准库函数(例如 fopen) (),当然还有 printf()
故障排除
所有 Windows 系统(自 Windows 95 起)上都有一个 C 标准库,即 MSVCRT.DLL。
要使用它,请导入它们的入口点,例如使用我的 msvcrt-light.lib (谷歌搜索)。但仍然存在一些警告,特别是在使用比 MSVC6 更新的编译器时:
- 堆栈帧仍然限制为 4 KB
- _ftol_sse 或 _ftol2_sse 必须路由到 _ftol
- _iob_func 必须路由到 _iob
它的初始化似乎在加载时运行。至少文件功能可以顺利运行。
老问题,但答案要么不正确,要么专注于一个特定问题。
如果程序实际上在 main/WinMain 上启动,则许多 C 和 C++ 功能在 Windows(或大多数操作系统)上根本不可用。
举个简单的例子:
class my_class
{
public:
my_class() { m_val = 5; }
int my_func(){ return m_val }
private:
int m_val;
}
my_class g_class;
int main(int argc, char **argv)
{
return g_class.my_func();
}
为了使该程序按预期运行,必须在 main 之前调用 my_class 的构造函数。如果程序恰好在 main 处启动,则需要编译器 hack(注意:GCC 在某些情况下会这样做)以在 main 的最开头插入函数调用。相反,在大多数操作系统和大多数情况下,不同的函数构造 g_class,然后调用 main(在 Windows 上,这是 mainCRTStartup 或 WinMainCRTStartup;在大多数其他操作系统上,我习惯它是一个名为 _start 的函数)。
C++ 甚至 C 还需要在 main 之前或之后完成其他事情才能工作。
main 启动后,如何使用 stdin 和 stdout(std::cin 和 std::cout)?
atexit 是如何工作的?
C 标准要求标准库具有类似 POSIX 的信号 API,在 Windows 上必须在 main() 之前“安装”。
在大多数操作系统上,没有系统提供的堆; C 运行时实现了自己的堆(Microsoft 的 C 运行时仅包装了 Kernel32 堆函数)。
即使传递给 main、argc 和 argv 的参数也必须以某种方式从系统获取。
您可能想看一下 Matt Pietrick 的(古老的)关于实现他自己的 C 运行时的文章,了解它如何与 Windows + MSVC 一起工作的具体信息(注意:MinGW 和 Cygwin 以不同的方式实现特定的东西,但实际上大多数事情都回落到 MSVCRT) ):
http://msdn.microsoft.com/en-us/library/bb985746.aspx
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
CRT 的入口点执行以下操作(此列表并不完整):
Visual Studio 提供了 CRT 源代码,您可以在调试器中单步执行 CRT 的入口点并准确了解它正在做什么。
The CRT's entry point does the following (this list is not complete):
The CRT source code is available with Visual Studio and you can step through the CRT's entry point in a debugger and find out exactly what it is doing.