Visual c++ WinMainCRTStartup执行哪些功能?

Visual c++ WinMainCRTStartup执行哪些功能?,visual-c++,crt,entry-point,winmain,Visual C++,Crt,Entry Point,Winmain,这是一系列至少两个密切相关但截然不同的问题的一部分。我希望我单独问他们是对的 我试图让我的Visual C++ 2008应用程序在没有C运行库的情况下工作。它是一个Win32 GUI应用程序,没有MFC或其他花哨的东西,只有普通的Windows API 因此,我将projectproperties->Configuration->C/C++->Advanced->省略默认库名称设置为Yes(编译器标志/Zl)并重新生成 然后链接器抱怨未解析的外部\u WinMainCRTStartup。公平地说

这是一系列至少两个密切相关但截然不同的问题的一部分。我希望我单独问他们是对的

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

因此,我将projectproperties->Configuration->C/C++->Advanced->省略默认库名称设置为Yes(编译器标志
/Zl
)并重新生成

然后链接器抱怨未解析的外部
\u WinMainCRTStartup
。公平地说,我可以告诉链接器使用不同的入口点,比如
MyStartup
。从我在网上收集的资料来看,
\u WinMainCRTStartup
做了一些初始化工作,我可能希望
MyStartup
做其中的一个子集

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

如果你对这些东西很了解,请也看看。谢谢

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

  • 我的应用程序没有明确使用任何CRT功能
  • 我喜欢精益和吝啬的应用程序
  • 它会教我一些新东西

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

    • 初始化CRT所需的全局状态。如果不这样做,您就不能使用CRT提供的任何功能或状态
    • 初始化编译器使用的某些全局状态。运行时检查,例如/GS使用的安全cookie,在这里非常突出。然而,你可以称你自己为。您可能需要为其他运行时检查添加其他代码
    • 调用C++对象上的构造函数。如果您正在编写C++代码,则可能需要对其进行仿真。
    • 检索操作系统提供的命令行和启动信息,并将其传递给主用户。默认情况下,操作系统不会将任何参数传递到程序的入口点,这些参数都是由CRT提供的
    Visual Studio提供了CRT源代码,您可以在调试器中逐步检查CRT的入口点,并确切地了解它在做什么。

    用C(不是C++)编写的真正的Win32程序根本不需要任何初始化,因此您可以使用WinMainCRTStartup()而不是WinMain启动项目(HINSTANCE,…)

    也可以将控制台程序编写为真正的Win32应用程序,但难度稍大;入口点的默认名称是\u mainCRTStartup()

    禁用所有额外的代码生成功能,如堆栈探测、数组检查等。仍然可以进行调试

    初始化 有时需要第一个HINSTANCE参数。对于Win32(Win32除外),它固定为(HINSTANCE)0x400000

    nCmdShow参数始终为SW\u SHOWDEFAULT

    如有必要,使用GetCommandLine()检索命令行

    终止 当程序生成线程时,例如通过调用GetOpenFileName(),从WinMainCRTStartup()返回return关键字将挂起程序-改用ExitProcess()

    警告 在以下情况下,您将遇到相当大的麻烦:

    • 使用大于4 KB(每个函数)的堆栈帧(即局部变量)
    • 使用浮点运算(例如浮点->整数转换)
    • 在32位机器上使用64位整数(乘法、位移位操作)
    • C++使用<强> > < <强> > <强>删除< /强>,所有非成员的静态对象构造器
    • 当然,使用标准库函数,如fopen()printf()
    故障排除 所有Windows系统(自Windows 95以来)上都有一个C标准库,MSVCRT.DLL

    要使用它,请导入它们的入口点,例如使用mymsvcrt light.lib(google for it)。但仍有一些注意事项,特别是在使用比MSVC6更新的编译器时:

    • 堆栈帧仍然限制为4KB
    • \u ftol\u sse\u ftol2\u sse必须路由到\u ftol
    • \u iob\u func必须路由到\u iob

    它的初始化似乎是在加载时运行的。至少文件函数会毫无征兆地运行。

    旧问题,但答案要么不正确,要么集中在一个特定的问题上

    有很多C和C++的特性,如果程序实际上在MIN/WINMANE下启动,则不能在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_类的构造函数。如果程序恰好在main处启动,则需要编译器破解(注意:GCC在某些情况下会这样做)在main的最开头插入函数调用。相反,在大多数操作系统上,在大多数情况下,不同的函数构造g_类,然后调用main(在Windows上,这是mainCRTStartup或WinMainCRTStartup;在我习惯的大多数其他操作系统上,这是一个名为_start的函数)

    <>在主操作之前或之后,还有其他C++和C需要做的事情。 一旦主设备启动,如何使用stdin和stdout(std::cin和std::cout)? atexit如何运作

    C标准要求标准库具有类似POSIX的信号API,在Windows上必须在main()之前“安装”

    在大多数操作系统上,没有系统提供的堆;C运行时实现自己的堆(Microsoft的C运行时只包装内核32堆函数)

    即使是传递给main、argc和argv的参数,也必须以某种方式从系统中获取