What functions does _WinMainCRTStartup perform?

余生颓废 提交于 2019-11-29 01:37:10

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.

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.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!