簡體   English   中英

g ++無法將.o文件鏈接到可執行文件

[英]g++ fails to link .o files into an executable

我正在我用來學習的教科書中進行示例練習。 我需要做的就是編譯,鏈接和運行以下3個文件:

//file my.h
extern int foo;
void print_foo();
void print(int);

my.h是一個簡單的頭文件,它聲明兩個函數和一個'global'int foo,沒有初始值。

//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

標志也導致相同的錯誤。

我正在將MacBook Pro與最新的macOS(實際上只是進行了更新)一起使用,如果這有助於解釋錯誤消息。

我嘗試初始化foo,但沒有進行任何更改。

另外,我嘗試過更新命令行工具,同樣的錯誤。

據我了解,錯誤告訴我,即使my.h包含在兩個文件中,也沒有人可以實際使用foo變量(它稱為_foo)實現任何函數,盡管它在my.h中已明確聲明。 。 我的猜測是鏈接器在后台使用了錯誤的名稱,這使得無法鏈接到可執行文件。 這是因為錯誤提到了一個

__Z9print_foov

在任何文件中都不存在。

此時似乎幾乎是g ++或macOS /命令行工具錯誤。 我不想每次都添加聲明,因為無論如何都會產生重復的符號錯誤。 將my.cpp和use.cpp放在一個文件中可能會正確鏈接,但是我需要確保實際上可以鏈接多個cpp文件,因為我最終(希望)將使用需要鏈接的多個cpp文件。 任何幫助表示贊賞!

我建議用兩個命令g++ -Wall -c my.cpp (給出一個my.o )和g++ -Wall -c use.cpp (給出use.o )來use.o ,然后用g++ my.o use.o -o myprog鏈接程序g++ my.o use.o -o myprog 其實你應該寫一個Makefile文件 (見這個靈感)和簡單的運行make

您的翻譯單元my.cppuse.cpp聲明了一些extern int foo; 從未定義的變量。 因此,您可能需要在一個文件中(而不是在其他文件中) 定義它,可能是通過添加(例如, 單獨添加到my.cpp

 int foo;

(不帶extern ),甚至帶有一些明確的初始值,例如int foo = 34;

這是因為錯誤中提到了__Z9print_foov ,該錯誤不存在

這是一個錯誤的名稱 ,在兩個對象文件中都引用了(但未定義 )(另請參閱this )。

此時似乎幾乎是g ++或macOS /命令行工具錯誤

您極不可能在編譯器工具中發現錯誤( GCCClang / LLVM都經過了嚴格的測試;由於它們是數百萬行的免費軟件,因此它們確實存在殘留的錯誤,但是您贏得彩票的機會要大於獲得錯誤的機會。受到編譯器錯誤的影響)。 我從1974年開始從事編碼工作,一生只有一次。 更現實的態度是要謙虛一些, 在懷疑編譯器或構建鏈之前先 自己的代碼 (和知識)。

順便說一句,始終首先編譯所有警告和調試信息(例如, g++ -Wall -g以及-Wextra )。 使用gdb調試器。 當您確信代碼沒有錯誤時,可以通過要求編譯器進行優化來對它進行基准測試(因此可以使用g++ -Wall -O2或也可以使用-g進行編譯)。

另請參閱鏈接器維基頁面。 深入閱讀C ++教科書 (另請參見本網站C ++ 11標准,例如n3337草案),以了解聲明定義某些變量或函數之間的區別 通常,您可以在一些通用標頭(包含在多個轉換單元中)中聲明一個全局extern變量,然后在其他位置進行一次定義,但是好的做法是避免使用很多全局變量。 另請參見C ++ 17新的內聯變量。

在這里,您聲明一個變量:

extern int foo;

然后使用變量:

cout << foo << endl;

但是您沒有在任何地方定義變量。 鏈接器錯誤表明鏈接器找不到變量的定義。 要解決這個問題,請輸入int foo; .cpp文件之一的文件范圍內。

在問題中,您說更改extern int foo; int foo; 給出相同的錯誤。 但是,如果您更仔細地查看錯誤消息,我想您會發現它給出了關於多種定義的另一種說法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM