代码之家  ›  专栏  ›  技术社区  ›  Sadique

开始执行

c++
  •  1
  • Sadique  · 技术社区  · 14 年前

    请告诉我C++从哪里开始执行,希望你的答案是“从主”。

    那这个呢?

    class abc
    { 
    public:
        abc()
        { 
            cout<<"hello";
        }
    };
    
    const abc obj;
    
    int main( )
    { 
        cout<<"Main";
    }
    

    输出:

    helloMain 
    

    请详细说明。

    5 回复  |  直到 14 年前
        1
  •  4
  •   Rakis    14 年前

    从你的评论到其他答案,这听起来像是一个10000英尺的视角可能有助于理解。

    启动应用程序的具体步骤在操作系统、编译器和编程语言之间有所不同,但“常规”过程基本上是相同的。

    1. 操作系统内核被要求启动一个运行目标可执行文件的新进程。
    2. 内核创建一个新进程来承载可执行的
    3. 内核设置基本的进程属性:文件描述符、环境变量、安全属性等。
    4. 内核运行一个用户模式的“加载器”,以实际打开包含可执行文件的文件,并准备好执行。
    5. 加载程序读取包含可执行文件的文件,并将其分为多个段:全局变量数据、可执行代码等。
    6. 加载程序解析任何动态链接库符号并为可执行代码正确地布局内存(本质上,此步骤涉及确保程序中的所有指针指向正确的位置)
    7. 然后,loder调用可执行文件的“entry”函数。但是,这不是您的“主要”功能。“entry”函数通常被OS/编译器隐藏,以允许运行主初始化前的代码。
    8. 在C++的情况下,输入函数很可能看起来像下面这样:

    int __entry( int argc, char *argv[] )
    {
        // configure standard I/O streams, threading tables, & other utilities
        initialize_c_runtime(); 
    
        // run the constructors for all static objects
        initialize_static_cplusplus_objects(); 
    
        // Now, finally, after *all* that we execute the 'main' function
        return main(argc, argv);
    }
    
        2
  •  12
  •   Amarghosh    14 年前

    全局变量是在 main 被调用。


    对OP评论的回答:

    如果你想比你写的代码更深入地挖掘,以前会发生一些事情 主要的 我自己也不清楚。我说的是我们编写的代码——入口点是 主要的 函数,在初始化全局变量后调用。实际上,类实例的初始化意味着调用其构造函数。

    因此,简而言之, const abc obj; 创建类型为的全局变量 abc 它是在 主要的 被称为。因此输出 helloMain

        3
  •  3
  •   Johannes Rudolph    14 年前

    你宣布 obj 作为类的常量变量 abc . 变量 OBJ 在程序开始执行之前,由编译器限定的代码分配一个默认值。此代码调用默认构造函数以创建类型为的默认对象 abc 并将其分配给 OBJ .

    撇开静态初始化不谈,正确的做法是说执行从 main() .

        4
  •  0
  •   MD Sayem Ahmed    14 年前

    自从 obj 是全局对象,它将在 main 执行。它与任何其他全局变量一样,也就是说,当您将一个整型变量声明为全局变量时,它包含0,而不是任何垃圾值。因此,您的对象正在实例化,并调用构造函数,该构造函数依次打印 hello 字符串。

        5
  •  0
  •   Ofek Shilon    14 年前

    应用程序不是从MAIN启动的。以下是使用VS2005编译的主(对于控制台应用程序,Unicode版本)开始时的一些堆栈快照:

    哦!WMIN(INTARC=0x000 000 01,WCHARYT**ARGV= 0x00 364D68)67行C++

    myapp.exe!__tmainCRTStartup()  Line 594 + 0x17 bytes    
    
    kernel32.dll!_BaseProcessStart@4()  + 0x23 bytes    
    

    可以说在用户模式下的新进程上下文中运行的第一个函数是baseprocessstart,它是一个Win32级别的函数。它调用CRT级别的mainCRTStartup,它使用二进制映像本身中的各种数据节来运行各种初始值设定项-例如,全局构造函数(如obj)。实际上,您可以在ctor中设置断点并自己观察它:

    哦!`'obj'()的动态初始值设定项

    MSVCR80.DLL!中期(…)

    哦!_ t增量启动()

    KNEL32.DLL!_ baseprocessstart@4()。

    (在格式化方面有一些困难)。 中期 循环访问全局对象并调用其构造函数的函数。

    在不同的平台和编译器上(甚至在vs上,对于一个mfc应用程序来说,这两个堆栈看起来是不同的),但其思想始终是相同的:运行时使用二进制图像信息来初始化全局对象 之前 您自己的主管道已进入。