The program starts to run from Main. Is the result of main finished?

Source: Internet
Author: User
Tags exit in

I saw a friend a few days ago and wanted to execute a piece of code before the main execution. I was not clear at the time, so I did not dare to rush to answer the question, for fear of misleading others. After figuring it out, I found that the post was gone and sweated.

 

Let's take a look at several small examples:

 

1.

 

# Include <stdio. h>

Int A = 3;

 

Int main (INT argc, char * argv [])
{
Printf ("the value of A is % d./N", );
Getchar ();
Return 0;
}

 

2.

 

# Include <iostream>
# Include <string>

Using namespace STD;

Class Test
{
Public:
Test ()
{
Cout <"this is a test" <Endl;
}
};

Test T;

Int main (INT argc, char * argv [])
{
Getchar ();
Return 0;
}

 

3.

 

# Include <iostream>
# Include <string>

Using namespace STD;

Void Foo ()
{
Cout <"after main..." <Endl;
}

Int main (INT argc, char * argv [])
{
Atexit (& Foo );
Cout <"End of main" <Endl;
Return 0;
}

 

4. Open the call stack when the main function in any of the above examples has a breakpoint, execution, and other interruptions.

 

-----------------------------------

 

In C/C ++ class, the teacher told us that the C/C ++ program starts to run from the main function, and the program ends when the main function returns.

After executing the above small programs, you may have been fooled for a long time?

1. Before the main execution, variable A is already our initial value 3. who helped us do it?

2. Main does not do anything. It just waits for the input and exits, but t is instantiated.

3. The main is over, and the foo function is executed!

 

Obviously, when the operating system loads the compiled program, the first code to be executed is not the first line of the main function, but some other code, these code makes all preparations for program execution: Prepare input and output, and prepare the Runtime Library. That is why our global variables have been initialized when main is not executed, the runtime libraries such as printf, cout, and * alloc can be used, and the command line parameters are waiting for us to obtain the reason. When the main function returns, it records the return value of main and executes the registered atexit function for cleanup, such as detaching the Runtime Library, after the memory is released, the process ends and the return value of main is handed over to the operating system.

 

Generally, the above Code is called an entry point function. For Ms VC ++, the name of this function is maincrtstartup. This function does two things: one is to initialize the Security cookie, mainly to prevent Stack Overflow; second, call _ tmaincrtstartup to perform further initialization here. If you are interested, you can check the source code of the CRT that comes with vs 2010, in Microsoft Visual Studio 10.0/VC/CRT/src/crtexe. c. paste some code here.

 

_ Declspec (noinline)
Int
_ Tmaincrtstartup (
Void
)
{
# Ifdef _ winmain _
_ Tuchar * lpszcommandline;
Startupinfow startupinfo;
Bool indoublequote = false;

Getstartupinfow (& startupinfo );
# Endif/* _ winmain _*/

# Ifdef _ m_ix86
/*
* Enable app termination when heap uption is detected on
* Windows Vista and above. This is a no-op on down-level OS's
* And enabled by default for 64-bit processes.
*/

If (! _ Noheapenableterminationonappsuption)
{
Heapsetinformation (null, heapenableterminationondeletion uption, null, 0 );
}
# Endif/* _ m_ix86 */

/*
* Guard the initialization code and the call to user's main, or
* Winmain, function in a _ Try/_ Wait t statement.
*/

_ Try
{
/*
* There is a possiblity that the module where this object is
* Linked into is a mixed module. In all the cases we gurantee that
* Native initialization will occur before managed initialization.
* Also in anycase this code shoshould never be called when some other
* Code is initializing native code, that's why we exit in that case.
*
* Do runtime startup initializers.
*
* Note: The only possible entry we'll be executing here is
* _ Lconv_init, pulled in from charmax. OBJ only if the EXE was
* Compiled with-J. All other. CRT $ Xi * initializers are only
* Run as part of the CRT itself, and so for the crt dll Model
* Are not found in the exe. For that reason, we call _ initterm,
* Not _ initterm_e, because _ lconv_init will never return failure,
* And _ initterm_e is not exported from the crt dll.
*
* Note further that, when using the crt dll, executing
*. CRT $ Xi * initializers is only done for an EXE, not for a DLL
* Using the crt dll. That is to make sure the-J setting
* The EXE is not overriden by that of any DLL.
*/
Void * lock_free = 0;
Void * maid = (pnt_tib) ntcurrentteb ()-> stackbase;
Int nested = false;
While (lock_free = interlockedcompareexchangepointer (volatile pvoid *) & __ native_startup_lock, fiber ID, 0 ))! = 0)
{
If (lock_free = fiber ID)
{
Nested = true;
Break;
}

/* Some other thread is running native startup/shutdown during a cctor/domain unload.
Shocould only happen if this DLL was built using the Everett-compat loader lock fix in vcclrit. h
*/
/* Wait for the other thread to complete init before we return */
Sleep (1000 );
}

If (_ native_startup_state = _ initializing)
{
_ Amsg_exit (_ rt_crt_init_conflict );
}
Else if (_ native_startup_state = _ uninitialized)
{
_ Native_startup_state = _ initializing;
# Ifndef _ syscrt
If (_ initterm_e (_ xi_a, _ xi_z )! = 0)
{
Return 255;
}
# Else/* _ syscrt */
_ Initterm (_ pvfv *) (void *) _ xi_a, (_ pvfv *) (void *) _ xi_z );
# Endif/* _ syscrt */
}
Else
{
Has_cctor = 1;
}

/*
* Do C ++ Constructors (initializers) specific to this exe
*/
If (_ native_startup_state = _ initializing)
{
_ Initterm (_ xc_a, _ xc_z );
_ Native_startup_state = _ initialized;
}
_ Asserte (_ native_startup_state = _ initialized );
If (! Nested)
{
/* For x86, the definition of interlockedexchangepointer wronugly causes warning c4312 */
# Pragma warning (push)
# Pragma warning (Disable: 4312)
Interlockedexchangepointer (volatile pvoid *) & __ native_startup_lock, 0 );
# Pragma warning (POP)
}

/*
* If we have any dynamically initialized _ declspec (thread)
* Variables, then invoke their initialization for the primary
* Thread used to start the process, by calling _ dyn_tls_init
* Through a callback defined in tlsdyn. obj.
*/
If (_ dyn_tls_init_callback! = NULL &&
_ Isnonwritableincurrentimage (pbyte) & __ dyn_tls_init_callback ))
{
_ Dyn_tls_init_callback (null, dll_thread_attach, null );
}

/* Enable buffer count checking if linking against static lib */
_ Crtsetcheckcount (true );

# Ifdef _ winmain _
/*
* Skip past program name (first token in command line ).
* Check for and handle quoted program name.
*/
# Ifdef wprflag
Lpszcommandline = (wchar_t *) _ wcmdln;
# Else/* wprflag */
Lpszcommandline = (unsigned char *) _ acmdln;
# Endif/* wprflag */

While (* lpszcommandline> spacechar |
(* Lpszcommandline & indoublequote )){
/*
* Flip the count from 1 to 0 or 0 to 1 if current character
* Is doublequote
*/
If (* lpszcommandline = dquotechar) indoublequote =! Indoublequote;
# Ifdef _ MBCS
If (_ ismbblead (* lpszcommandline )){
If (lpszcommandline ){
Lpszcommandline ++;
}
}
# Endif/* _ MBCS */
++ Lpszcommandline;
}

/*
* Skip past any white space preceeding the second token.
*/
While (* lpszcommandline & (* lpszcommandline <= spacechar )){
Lpszcommandline ++;
}

# Ifdef wprflag
Mainret = wwinmain (
# Else/* wprflag */
Mainret = winmain (
# Endif/* wprflag */
(Hinstance) & __ imagebase,
Null,
Lpszcommandline,
Startupinfo. dwflags & startf_useshowwindow
? Startupinfo. wshowwindow
: Sw_showdefault
);
# Else/* _ winmain _*/

# Ifdef wprflag
_ Winitenv = envp;
Mainret = wmain (argc, argv, envp );
# Else/* wprflag */
_ Initenv = envp;
Mainret = Main (argc, argv, envp );
# Endif/* wprflag */

# Endif/* _ winmain _*/

/*
* Note that if the EXE is managed app, we don't really need
* Call exit or _ c_exit .. cctor shocould be able to take care
* This.
*/
If (! Managedapp)
Exit (mainret );

If (has_cctor = 0)
_ Cexit ();

}
_ Effect (_ xcptfilter (getexceptioncode (), getexceptioninformation ()))
{
/*
* Shoshould never reach here
*/

Mainret = getexceptioncode ();

/*
* Note that if the EXE is managed app, we don't really need
* Call exit or _ c_exit .. cctor shocould be able to take care
* This.
*/
If (! Managedapp)
_ Exit (mainret );

If (has_cctor = 0)
_ Cexit ();
}/* End of try-else t */

Return mainret;
}

 

Now back to the first topic, there is a way to execute code before the main function, that is, to add the initialization function by yourself.

The following is an example of adding custom initialization code in VC ++ 2010:

 

# Include <iostream>

 

// Defines the name of the section in which our init code stored.
# Define scname ". CRT $ XCI"

 

# Pragma section (scname, long, read)

 

Using namespace STD;

 

Void Foo ()
{
Cout <"Initializing..." <Endl;
}

 

Typedef void (_ cdecl * _ pvfv )();
_ Declspec (allocate (scname) _ pvfv dummy [] = {Foo };

 

Int main (INT argc, char * argv [])
{
Getchar ();
Return 0;
}

 

 

The original definition of _ pvfv is in CRT/Internal. h and serves as a function pointer to a function without parameters or return values.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.