2014-06-11 54 views
6

假設我有兩個源文件 - UndefErr.cpp有沒有辦法忽略未使用的未定義的引用?

#include <cstdio> 

void UndefFunc(); 
void Func2(){UndefFunc();} 

void Func1(){printf("Hi\n");} 

而且main.cpp中

void Func1(); 

int main(){ 
    Func1(); 
    return 0; 
} 

當您在UndefErr.cpp看到Func2()會觸發錯誤,因爲它使用未定義的UndefFunc()。但主要功能並不在乎Func2()!根據a relevant question我可以通過一個選項- 解析符號= ignore-in-object-files到鏈接器,但我想要一個有點不同的東西。我需要一個鏈接器來知道未定義的函數是否在某處使用,然後纔會失敗。

之所以問這麼奇怪的問題是,我試圖用一個lwIP,這是很難理解其所有相關的(我只需要TCP/IP),我無法找到互聯網上的教程。所以我想我可以分別編譯大多數(或所有) .c文件,並編寫一些簡單的測試以查看它的功能。但是這種方法在「未定義的引用」上絆腳石,其中大多數可能與用例無關。

+0

看起來好像鏈接器可以「找出」,如果引用甚至需要解決......但一個解決方案是,如果沒有太多的功能,使它很麻煩,你可以將它們存儲在主要。 cpp ...例如'void UndefFunc(){}' – mark

+0

@mark no,在這個項目中有很多功能。而我不知道的主要問題,哪些功能沒有使用,這就是爲什麼我想以某種方式自動化它.. –

+0

我不明白這個問題。鏈接器會在遇到未定義的函數時發出抱怨。 –

回答

4

用gcc 4.8.2,我設法代碼沒有錯誤有以下鏈接:

$ g++ -c main.cpp -O3 -flto 
$ g++ -c UndefErr.cpp -O3 -flto 
$ g++ main.o UndefErr.o -flto -O3 -o out 

我知道-flto將使連接器表現得好像-fwhole-program傳遞,整個事情是一個單一的編譯單元。根據手冊,-fwhole-program對應於函數的正確使用static,因此允許從輸出中消除未使用的函數(也就是說,您可以確保編譯器將所有函數都不會被其他代碼使用,可能會動態加載,並且您爲用戶保證的唯一入口點是main())。

我不得不添加-O3,我不確定爲什麼,但編譯器對檢查函數和消除死代碼沒有興趣。

+0

非常好,我從來不知道這個選項!是的,如果沒有'-O3'在編譯時傳遞,鏈接器出於某種原因拒絕中止未使用的函數。 –

+1

使用MinGW GCC 5.3.0的MSYS2版本,我能夠實現消除未使用的函數,因此避免了對用'-flto -Og'編譯器選項引用的那些函數符號的「未定義引用」錯誤 –

3

問題是您的未定義函數使用。 Func2的目標代碼已經生成,有一個對未知的UndefFunc的引用,並且它轉到鏈接器。編譯器無法理解該函數總是未定義,因爲有多個翻譯單元。

避免編譯錯誤的唯一方法是告訴鏈接器您不需要使用未使用函數的對象代碼,以便它不會嘗試爲這種情況生成程序集。

+1

我已經找到了,我只是發現可能需要兩件事:使用'-fdata-sections -ffunction-sections'作爲標誌,以便每個函數都在它自己的部分中(以允許鏈接器看到一個部分之間的引用),然後鏈接器需要知道確切的函數(在我的情況下是* main *),從中需要跟蹤引用。我也剛剛發現* LD *有一種腳本語言,所以可能我在這裏 - 看起來,沒有一種標準的方法來做我想要的。 –

+0

我認爲值得一提的是,在上述場景中,我應該從'_start'函數進行跟蹤,因爲它是第一個要執行的函數。否則,我可能最終會破壞可執行文件。 –

相關問題