c++ 在main 之前的全局對象

問題:
google c++ 編程規範要求全局對象,應該用指針代替。指出類的構造函數在 main 之前執行是一個未定義的行爲。

查看資料之後,兩大主流編譯器 g++ , vs它們對於全局對象的處理是這樣的。。。

在 main() 函數開始之前先執行了一個 _start() 的函數。這個函數做了一些運行程序的初始化的操作。
證明:

class Test
{
public:
    Test()
    {
        std::cout << "Test construct" << std::endl;
    }
};


Test a;

int main()
{
    std::cout << "main is start" << std::endl;
}

g++ test.cpp -std=c++11 -nostdlib
報錯找不到入口函數 _start。
並且可定看到全局對象 std::cout 這些對象找不到。那說明在 _start 裏有構造一個全局的 std::cout .

/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 00000000004001b4
/tmp/ccYGqkKV.o:在函數‘main’中:
test.cpp:(.text+0xa):對‘std::cout’未定義的引用
test.cpp:(.text+0xf):對‘std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)’未定義的引用
test.cpp:(.text+0x14):對‘std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)’未定義的引用
test.cpp:(.text+0x1c):對‘std::ostream::operator<<(std::ostream& (*)(std::ostream&))’未定義的引用
/tmp/ccYGqkKV.o:在函數‘__static_initialization_and_destruction_0(int, int)’中:
test.cpp:(.text+0x4a):對‘std::ios_base::Init::Init()’未定義的引用
test.cpp:(.text+0x4f):對‘__dso_handle’未定義的引用
test.cpp:(.text+0x59):對‘std::ios_base::Init::~Init()’未定義的引用
test.cpp:(.text+0x5e):對‘__cxa_atexit’未定義的引用
/tmp/ccYGqkKV.o:在函數‘Test::Test()’中:
test.cpp:(.text._ZN4TestC2Ev[_ZN4TestC5Ev]+0x12):對‘std::cout’未定義的引用
test.cpp:(.text._ZN4TestC2Ev[_ZN4TestC5Ev]+0x17):對‘std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)’未定義的引用
test.cpp:(.text._ZN4TestC2Ev[_ZN4TestC5Ev]+0x1c):對‘std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)’未定義的引用
test.cpp:(.text._ZN4TestC2Ev[_ZN4TestC5Ev]+0x24):對‘std::ostream::operator<<(std::ostream& (*)(std::ostream&))’未定義的引用
/usr/bin/ld: a.out: hidden symbol `__dso_handle' isn't defined
/usr/bin/ld: 最終連接失敗: 錯誤的值
collect2: error: ld returned 1 exit status

主要工作:
1.設置棧指針
2.初始化static靜態和global全局變量,即data段的內容
3.將未初始化部分的賦初值:數值型short,int,long等爲0,bool爲FALSE,指針爲NULL,等等,即.bss段的內容
4.運行全局構造器,估計是C++中構造函數之類的吧
5.將main函數的參數,argc,argv等傳遞給main函數,然後才真正運行main函數

總結:
不同的編譯器對於 main 之前調用的函數可能不同。但是所做的事情基本一樣。都會調用全局對象的構造函數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章