_WinMainCRTStartup 执行什么功能?

发布于 2024-08-08 16:28:18 字数 847 浏览 3 评论 0原文

这是一系列至少两个密切相关但又截然不同的问题的一部分。我希望通过单独询问他们来做正确的事情。

我正在尝试让我的 Visual C++ 2008 应用程序在没有 C 运行时库的情况下运行。它是一个 Win32 GUI 应用程序,没有 MFC 或其他花哨的东西,只是简单的 Windows API。

所以我设置了项目属性->配置-> C/C++->高级->将默认库名称省略为“是”(编译器标志 /Zl)并重建。

然后链接器抱怨未解析的外部 _WinMainCRTStartup。公平地说,我可以告诉链接器使用不同的入口点,例如 MyStartup。根据我在网络上收集的信息,_WinMainCRTStartup 执行一些初始化操作,我可能希望 MyStartup 执行其中的一部分。

所以我的问题是:_WinMainCRTStartup 执行哪些功能,如果不使用 CRT,我可以省略哪些功能?

如果您对此了解东西,请看看 我的还有其他问题。谢谢!

旁白:为什么我首先要这样做?

  1. 我的应用程序没有明确使用任何 CRT 函数。
  2. 我喜欢精益且简单的应用程序。
  3. 它会教我一些新东西。

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?

  1. My app doesn't explicitly use any CRT functions.
  2. I like lean and mean apps.
  3. It'll teach me something new.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苦笑流年记忆 2024-08-15 16:28:18

CRT 的入口点执行以下操作(此列表并不完整):

  • 初始化 CRT 所需的全局状态。如果不这样做,您将无法使用 CRT 提供的任何功能或状态。
  • 初始化编译器使用的某些全局状态。运行时检查(例如 /GS 使用的安全 cookie)在这里绝对很突出。不过,您可以自己调用 __security_init_cookie 。您可能需要添加其他代码以进行其他运行时检查。
  • 调用 C++ 对象的构造函数。如果您正在编写 C++ 代码,您可能需要对此进行模拟。
  • 检索操作系统提供的命令行和启动信息,并将其传递给您的 main.c 文件。默认情况下,操作系统不会将任何参数传递到程序的入口点 - 它们全部由 CRT 提供。

Visual Studio 提供了 CRT 源代码,您可以在调试器中单步执行 CRT 的入口点并准确了解它正在做什么。

The CRT's entry point does the following (this list is not complete):

  • Initializes global state needed by the CRT. If this is not done, you cannot use any functions or state provided by the CRT.
  • Initializes some global state that is used by the compiler. Run-time checks such as the security cookie used by /GS definitely stands out here. You can call __security_init_cookie yourself, however. You may need to add other code for other run-time checks.
  • Calls constructors on C++ objects. If you are writing C++ code, you may need to emulate this.
  • Retrieves command line and start up information provided by the OS and passes it your main. By default, no parameters are passed to the entry point of the program by the OS - they are all provied by the CRT.

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.

金橙橙 2024-08-15 16:28:18

用 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++ newdelete进行乘法、位移操作)
  • 的具有非清零所有成员构造函数的静态对象
  • ,以及使用标准库函数(例如 fopen) (),当然还有 printf()

故障排除

所有 Windows 系统(自 Windows 95 起)上都有一个 C 标准库,即 MSVCRT.DLL

要使用它,请导入它们的入口点,例如使用我的 msvcrt-light.lib (谷歌搜索)。但仍然存在一些警告,特别是在使用比 MSVC6 更新的编译器时:

  • 堆栈帧仍然限制为 4 KB
  • _ftol_sse_ftol2_sse 必须路由到 _ftol
  • _iob_func 必须路由到 _iob

它的初始化似乎在加载时运行。至少文件功能可以顺利运行。

A true Win32 program written in C (not C++) doesn't need any initialization at all, so you can start your project with WinMainCRTStartup() instead of WinMain(HINSTANCE,...).

It's also possible but a bit harder to write console programs as true Win32 applications; the default name of entry point is _mainCRTStartup().

Disable all extra code generation features like stack probes, array checks etc. Debugging is still possible.

Initialization

Sometimes you need the first HINSTANCE parameter. For Win32 (except Win32s), it is fixed to (HINSTANCE)0x400000.

The nCmdShow parameter is always SW_SHOWDEFAULT.

If necessary, retrieve the command line with GetCommandLine().

Termination

When your program spawns threads, e.g. by calling GetOpenFileName(), returning from WinMainCRTStartup() with return keyword will hang your program — use ExitProcess() instead.

Caveats

You will run into considerable trouble when:

  • using stack frames (i.e. local variables) larger than 4 KBytes (per function)
  • using float-point arithmetic (e.g. float->int conversion)
  • using 64-bit integers on 32-bit machines (multiply, bit-shift operations)
  • using C++ new, delete, and static objects with non-zero-out-all-members constructors
  • using standard library functions like fopen(), printf() of course

Troubleshoot

There is a C standard library available on all Windows systems (since Windows 95), the MSVCRT.DLL.

To use it, import their entry points, e.g. using my msvcrt-light.lib (google for it). But there are still some caveats, especially when using compilers newer than MSVC6:

  • stack frames are still limited to 4 KBytes
  • _ftol_sse or _ftol2_sse must be routed to _ftol
  • _iob_func must be routed to _iob

Its initialization seems to run at load time. At least the file functions will run seemlessly.

难忘№最初的完美 2024-08-15 16:28:18

老问题,但答案要么不正确,要么专注于一个特定问题。

如果程序实际上在 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

Old question, but the answers are either incorrect or focus on one specific problem.

There are a number of C and C++ features that simply will not be available on Windows (or most operating systems, for that matter) if the programs actually started at main/WinMain.

Take this simple example:

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();
}

in order for this program to function as expected, the constructor for my_class must be called before main. If the program started exactly at main, it would require a compiler hack (note: GCC does this in some cases) to insert a function call at the very beginning of main. Instead, on most OSes and in most cases, a different function constructs g_class and then calls main (on Windows, this is either mainCRTStartup or WinMainCRTStartup; on most other OSes I'm used to it is a function called _start).

There's other things C++ and even C require to be done before or after main to work.
How are stdin and stdout (std::cin and std::cout) useable as soon as main starts?
How does atexit work?

The C standard requires the standard library have a POSIX-like signal API, which on Windows must be "installed" before main().

On most OSes, there is no system-provided heap; the C runtime implements its own heap (Microsoft's C runtime just wraps the Kernel32 Heap functions).

Even the arguments passed to main, argc and argv, must be gotten from the system somehow.

You might want to take a look at Matt Pietrick's (ancient) articles on implementing his own C runtime for specifics on how this works with Windows + MSVC (note: MinGW and Cygwin implement specific things differently, but actually fall back to MSVCRT for most things):
http://msdn.microsoft.com/en-us/library/bb985746.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文