我正在做一個示例演練,在我用來學習的教科書中。所有我需要做的是編譯,鏈接並運行以下3個文件:g ++無法將.o文件鏈接到可執行文件中
//file my.h
extern int foo;
void print_foo();
void print(int);
my.h是聲明兩個函數和一個「全球」廉政富,無初始值的簡單的頭文件。
//file my.cpp
#include "my.h"
#include "std_lib_facilities.h" //not included but not source of error
void print_foo()
{
cout << foo << endl;
}
void print(int i)
{
cout << i << endl;
}
my.cpp包含從my.h包含的函數的實現。 std_lib_facilities.h是教科書中的一個文件,不是錯誤的根源(根據g ++)。如果需要,我可以將其編輯到問題的正文中。
//file use.cpp
#include "my.h"
#include <iostream>
int main() {
foo = 7;
print_foo();
print(99)
char cc; cin >> cc;
return 0;
}
use.cpp作爲這一計劃的主要執行文件,並嘗試使用所有這三個聲明&定義的對象。
我採用了兩步命令的方法來構建使用g ++。首先,我編譯了兩個.cpp文件:
g++ -c my.cpp use.cpp
它創建了兩個目標文件my.o和use.o.我用下面的命令將它們連接:
g++ -o myprog my.o use.o
給我這個錯誤:
Undefined symbols for architecture x86_64:
"_foo", referenced from:
print_foo() in my.o
_main in use.o
(maybe you meant: __Z9print_foov)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我試圖把
int foo;
到my.h而不是
extern int foo;
這給了我同樣的錯誤。
我已經使用
-std=c++11
標誌以及這就造成了同樣的錯誤嘗試。
我正在使用帶有最新macOS(實際上已更新)的MacBook Pro,如果這有助於解釋錯誤消息。
我試圖初始化foo,它並沒有改變任何東西。
另外,我試過更新命令行工具,同樣的錯誤。
從我所瞭解的錯誤告訴我,即使my.h包含在兩個文件中,儘管它明確聲明,但實際上它們都不能使用foo變量(它調用_foo)實現任何函數在my.h中。我的猜測是鏈接器在引擎蓋下使用了錯誤的名稱,這使得無法鏈接到可執行文件。這來自錯誤提及的一個事實
__Z9print_foov
它在任何文件中都不存在。
在這一點上,它幾乎看起來像一個g ++或macOS /命令行工具錯誤。我不想每次都添加聲明,因爲無論如何這會造成重複的符號錯誤。把我的.cpp和使用。cpp到一個文件可能會鏈接正確,但我需要確保我可以實際鏈接多個cpp文件,因爲我最終(希望)會與需要鏈接的多個cpp文件一起工作。任何幫助表示讚賞!
Declared int foo;在my.cpp中;有效!感謝您的幫助。但是我不明白爲什麼鏈接器有問題,但是如果變量是在頭文件中聲明的,因此在包含它的.cpp文件中聲明(除非我丟失了某些東西)。如果我不得不在.cpp文件中再次聲明它,那麼在頭文件中聲明extern int foo有什麼意義?爲了約定?我不認爲這個extern做了什麼特別的事情,但仍然很好奇,以至於我再也沒有這個問題。 – gasoline
閱讀更多關於聲明變量和定義變量之間差異的C++書籍。 –
夠公平的。這個bug的評論比其他任何內容都更令人沮喪,並不打算破壞gcc的努力。會試着更謙虛一點。感謝您花時間給我建議,而不僅僅是回答問題!我讀了一些文檔,並意識到即使沒有任何初始化值,plain int foo也被視爲一個聲明和一個定義,而頭部中的extern int foo聲明沒有定義,因此未定義,導致我的錯誤。 – gasoline