main和mainCRTStartup有什么区别?

时间:2014-04-08 10:24:35

标签: winapi

我试图理解如何替换WinMain的不同入口点在Microsoft工具链中起作用。

我已经找到this question并且它非常有用,但最后一个细节却在唠叨我。

我第一次在Visual Studio中更改Linker>Advanced>Entry Point选项时,我错误地将其设置为main并且我的程序已编译并运行正常。我后来意识到并重建了程序,并将其设置为mainCRTStartup,因为链接问题中的接受答案表明,并没有找到任何不同的内容。

所以,我的问题是:mainmainCRTStartup之间是否存在任何差异,若然,有什么区别?

2 个答案:

答案 0 :(得分:17)

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

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

class Foo {
public:
    Foo() {
        std::cout << "init done" << std::endl;
    }
} TestInit;

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

这很糟糕。

答案 1 :(得分:0)

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

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

int main()
{

}

在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

因此,程序入口点为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

所以main()成为程序的入口点,由于完全不调用CRT初始化函数,因此此时v的值为0,因此不会调用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()
{

}

并将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

,并且v将再次为1。程序入口点是entry(),它调用mainCRTStartup(),后者调用CRT初始化函数,然后调用func()来初始化init v,mainCRTStartup()最终调用main()。