main和mainCRTStartup有什么区别?

Mic*_*ael 9 winapi

我试图理解如何用不同的入口点代替WinMainMicrosoft工具链中的工作.

我已经发现了这个问题并且它非常有用,但最后一个细节却在唠叨我.

我第一次Linker>Advanced>Entry Point在Visual Studio中更改了选项时,我将其设置为main错误,我的程序编译并运行正常.我后来意识到并重建了程序设置为mainCRTStartup,如链接问题中接受的答案所示,并没有发现任何不同.

所以,我的问题是:是否有任何差异之间的所有mainmainCRTStartup,如果是这样,有什么区别?

Han*_*ant 17

main()是C或C++程序的入口点.mainCRTStartup()是C运行时库的入口点.它初始化CRT,调用你在代码中编写的任何静态初始值设定项,然后调用你的main()函数.

显然,首先执行CRT和您自己的初始化是至关重要的.如果没有发生,你可能会很难诊断出错误.也许你不会,这是一个废话.您可以通过在小型C++程序中粘贴此代码来测试的内容:

class Foo {
public:
    Foo() {
        std::cout << "init done" << std::endl;
    }
} TestInit;
Run Code Online (Sandbox Code Playgroud)

如果将入口点更改为"main",那么您将看到构造函数永远不会被调用.

这是不好的.

  • 作为旁注,C和C++之间的行为有什么不同? (2认同)

jw_*_*jw_ 7

在VS2017中,创建一个控制台C++应用程序:

#include "pch.h"
#include <iostream>
int func()
{
    return 1;
}
int v = func();

int main()
{

}
Run Code Online (Sandbox Code Playgroud)

在main()中设置断点并开始调试,然后调用堆栈如下:

testCppConsole.exe!main() Line 8    C++
testCppConsole.exe!invoke_main() Line 78    C++
testCppConsole.exe!__scrt_common_main_seh() Line 288    C++
testCppConsole.exe!__scrt_common_main() Line 331    C++
testCppConsole.exe!mainCRTStartup() Line 17 C++
kernel32.dll!@BaseThreadInitThunk@12()  Unknown
ntdll.dll!__RtlUserThreadStart()    Unknown
ntdll.dll!__RtlUserThreadStart@8()  Unknown
Run Code Online (Sandbox Code Playgroud)

所以程序入口点是mainCRTStartup,它最终调用C入口点main(),v的值为1。

现在将 Linker>Advanced>Entry Point 设置为“main”并开始调试,现在调用堆栈为:

>   testCppConsole.exe!main() Line 8    C++
    kernel32.dll!@BaseThreadInitThunk@12()  Unknown
    ntdll.dll!__RtlUserThreadStart()    Unknown
    ntdll.dll!__RtlUserThreadStart@8()  Unknown
Run Code Online (Sandbox Code Playgroud)

所以main()成为程序入口点,此时v的值为0,因为CRT init函数根本没有被调用,所以func()不会被调用。

现在将代码修改为:

#include "pch.h"
#include <iostream>

extern "C" int mainCRTStartup();
extern "C" int entry()
{
    return mainCRTStartup();
}

int func()
{
    return 1;
}
int v = func();

int main()
{

}
Run Code Online (Sandbox Code Playgroud)

并将 Linker>Advanced>Entry Point 设置为“entry”并开始调试,现在调用堆栈为:

>   testCppConsole.exe!main() Line 14   C++
    testCppConsole.exe!invoke_main() Line 78    C++
    testCppConsole.exe!__scrt_common_main_seh() Line 288    C++
    testCppConsole.exe!__scrt_common_main() Line 331    C++
    testCppConsole.exe!mainCRTStartup() Line 17 C++
    testCppConsole.exe!entry() Line 10  C++
    kernel32.dll!@BaseThreadInitThunk@12()  Unknown
    ntdll.dll!__RtlUserThreadStart()    Unknown
    ntdll.dll!__RtlUserThreadStart@8()  Unknown
Run Code Online (Sandbox Code Playgroud)

程序入口点是entry(),它调用mainCRTStartup(),mainCRTStartup()调用CRT init函数,CRT init函数调用func()来初始化v,mainCRTStartup()最终调用main()。