/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start': (.text+0x24): undefined reference to `main' coll ...
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
在使用g++編譯鏈接兩個C++源文件main.cpp以及VecAdd.cpp時出現了以上編譯報錯。main.cpp中引用了VecAdd.cpp中定義的函數vecAdd來實現兩個向量的加法。我們先說原因,再來分析一下g++為什麼會報這樣的錯誤。出現這個error的根本原因是錯誤地將g++命令行指令
linux> g++ -o main main.cpp VecAdd.cpp
寫成了
linux> g++ -o main.cpp VecAdd.cpp
這樣,g++會認為我們想要對VecAdd.cpp進行編譯,得到一個名為main.cpp的可執行文件。而違背了我們的本意:將main.cpp與VecAdd.cpp編譯並鏈接,得到可執行文件main. 在實驗下,以上錯誤的指令不僅達不成我們的目的,還會將我們的C++源文件main.cpp給吃掉,很傻:
再從鏈接器的角度審視一下這個錯誤:第一行的目錄/usr/bin/ld是鏈接器的路徑,第二行的(.text+0x24)表示目標文件出現錯誤的地方,也就是VecAdd.cpp對應的ELF格式的目標文件.text這一節(代碼段)中地址偏移為0x24的地方。這裡的undefined reference to main是什麼意思? 一開始作者以為是對“main”這個符號的引用沒有被定義,後來發現不是這樣。做了實驗後,發現真正的原因是:“在VecAdd.cpp中沒有定義main函數”。我們編寫了一個test.cpp.其中只有一條變數定義語句:
//test.cpp int a = 5;
使用指令
linux> g++ -o test test.cpp
來將test.cpp編譯成可執行文件,發現鏈接器報了同樣的錯誤:
於是,問題得到瞭解答:g++ 的 -o 選項是將源代碼編譯成可執行文件,而C++源程式的程式入口是main函數,在最初的例子中:
linux> g++ -o main.cpp VecAdd.cpp
由於錯誤輸入,這條指令這是將VecAdd.cpp編譯成名為main.cpp的可執行文件,而VecAdd.cpp中實現的是向量加法函數vecAdd,該源文件並沒有主函數main(),於是就出現了"undefined reference to main"的鏈接器報錯。
可以通過使用IDE、編寫shell腳本、使用cmake工具等更安全的工具,從而減少這樣的失誤帶來的問題。