C/C++程式在main之前執行代碼

來源:互聯網
上載者:User

標籤:完成   names   after   全域   -o   記憶體   nat   初始化   結構   

來源:《周哥教IT.C語言深學活用》https://ke.qq.com/course/242707#tuin=a71606

       我們在學習C/C++語言的時候,通常認為main函數是整個程式執行的開始。實際上,在main函數之前,會有一系列初始化的操作,這樣的操作通常是由連結器等完成的。具體說來,程式最早執行的函數其實並不是main,在windows中,是mainCRTStartup,這個函數是連結器執行以初始化執行階段程式庫的,此函數又會調用CRTInit函數,該函數會對C全域變數、C記憶體配置以及C++中的全域類對象和建構函式進行初始化工作。所以想要在main函數之前執行一些自己的代碼,是有可能的。

1. Linux環境下利用gcc的__attribute關鍵字

       在Linux環境的C編程中,可以利用__attribute關鍵字定義constructor和destructor,其中前者會在main函數之前執行,後者會在main函數之後執行。

       代碼如下:

 1 #include <stdio.h> 2  3 __attribute((constructor)) void before_main() 4 { 5     printf("before main!\n"); 6 } 7  8 __attribute((destructor)) void after_main() 9 {10     printf("after main!\n");11 }12 13 int main(void)14 {15     printf("This is main function.\n");16     return 0;17 }
before_main.c

       運行結果:

[email protected]:~/Desktop/zhou_it_c/before_main$ gcc before_main.c -o before_main

[email protected]:~/Desktop/zhou_it_c/before_main$ ./before_main
before main!
This is main function.
after main!

2. Windows環境下利用#pragma預定義

       上面我們說過CRTInit函數中會做一些初始化工作,包括C庫、C的初始化函數、C++庫、C++的初始化函數等。C和C++分別有一張表來儲存初始化函數指標,每個表又會使用2個指標來明確範圍。在初始化過程中,__CRTInit函數會一次調用這兩個表中的函數,所以如果我們能把要執行的函數放在這兩個表中,那麼就可以達到在main之前執行代碼的目的了。

       C初始化函數表的範圍是:[ __xi_a, __xi_a ] C++初始化函數表的範圍是:[ __xc_a, __xc_z]

       我們在具體執行的時候,通過定義特殊的段名稱“.CRT$XIU”和“.CRT$XCU”,把要執行的函數放在段中。連結器就會形成日下的C初始化函數表:

       [__xi_a, ..., before1(xiu), ..., __xi_z]

       以及C++初始化函數表:

       [__xc_a, ..., before2(xcu), ..., __xc_z]

       代碼如下:

#include <stdio.h>int before_main(void){    printf("before main!\n");    return 0;}typedef int func();#pragma data_seg(".CRT$XIU")static func *before[] = { before_main };#pragma data_seg()int main(void){    printf("This is main function.\n");    return 0;}
before_main.c

3. C++編程中利用定義全域類對象or全域變數

       mainCRTStartup會對全域對象a初始化,也就是說a的構造含稅會先於main執行,所以只需要在a的建構函式中定義我們要執行的函數。

       另一種方式是定義一個全域變數為函數運行後的結構,那麼該函數就會用於初始化,會先於main執行。

       代碼如下:

 1 #include <iostream> 2 using namespace std; 3 using std::cout; 4  5 int func() 6 { 7     cout <<"before main: func()" << endl; 8     return 0; 9 }10 11 class A12 {13 public:14     A()15     {16         cout << "A() constructor" << endl;17     }18     ~A()19     {20         cout << "A() destructor" << endl;21     }22 };23 24 A a;25 26 int g_iValue = func();27 28 int main(void)29 {30     cout << "This is main function." << endl;31     return 0;32 }
before_main.cpp

       運行結果:

A() constructor
before main: func()
This is main function.
A() destructor

C/C++程式在main之前執行代碼

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.