主函数和mainCRTStartup之间有什么区别?

15

我正在尝试理解如何在Microsoft工具链中替换不同的入口点WinMain

我已经找到了这个问题,它非常有帮助,但我还有一个细节困扰着我。

第一次在Visual Studio中更改Linker>Advanced>Entry Point选项时,我错误地将其设置为main,但我的程序编译和运行都正常。后来我意识到这个错误并使用建议中的mainCRTStartup重新构建程序,但没有发现任何不同之处。

因此,我的问题是: mainmainCRTStartup之间是否有任何区别,如果有,是什么区别?


19
mainCRTStartup 基本上看起来像这样:init_tls(); init_crt(); run_global_constructors(); get_args(&argc, &argv); ret = main(argc, argv); run_global_destructors(); exit(ret);。因此,main 函数在其中某个位置。 - Damon
2个回答

27

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

显然,确保先执行CRT和您自己的初始化非常重要。如果这不发生,您可能会遭受相当难以诊断的错误。也许您不会,这是个游戏。您可以通过将此代码粘贴到小型C++程序中进行测试来验证此事:

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

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

这很糟糕。


6

在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",并开始进行调试,此时调用堆栈(Call Stack)如下:

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

所以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()
{

}

并设置链接器>高级>入口点为“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()来初始化v,最终mainCRTStartup()调用main()。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接