2011-04-05 4 views
39

GCCはではありませんは未定義の関数を呼び出すときに "未定義の参照"リンクエラーメッセージをスローすることができますか?例えばGCCは未定義の参照について不平を言うことはできませんか?

、このCコードはGCCでコンパイルおよびリンクされている状況:

void function() 
{ 
    made_up_function_name(); 
    return; 
} 

... made_up_function_nameが存在しないにもかかわらずどこでもコード内(ないヘッダ、ソースファイル、宣言、第三者の図書館など)。

実際のコードに触れることなく、特定の条件の下でGCCによってその種のコードを受け入れ、コンパイルすることはできますか?もしそうなら、どちら?

ありがとうございました。

EDIT:made_up_function_nameへの前回の宣言や言及は他にはありません。つまり、ファイルシステム全体のうちgrep -Rの場合は、だけがその1行のコードを正確に示します。

+0

これは(C++ではなくCをコンパイルしている限り)行うことができます。あなたは何を達成しようとしていますか? –

+0

私は何かを達成しようとしていない、それはすでに起こっていると私はそれが可能な理由を知りたいです。 "-g"を使用し、テキストエディタでファイルを編集すると、最終的にリンクされたバイナリにmade_up_function_nameが実際に存在します。 – STenyaK

+1

理由は、http://stackoverflow.com/questions/4914589/c-prototype-functions/4914683、http://stackoverflow.com/questions/4800102/not-including-stdlib-h-does-notを参照してください。 -produce-any-compiler-error/4800138#4800138、そして多分もっと多くのものがあります。 –

答えて

68

はい、--unresolved-symbolsリンカオプションを使用して、未定義の参照を報告しないようにすることは可能です。

g++ mm.cpp -Wl,--unresolved-symbols=ignore-in-object-files 

man ldから--unresolved-シンボル=法

未解決のシンボルをどのように処理するかを決定します。 - [無]のallow-shlibの未定義オプション

 ignore-all 
      Do not report any unresolved symbols. 

     report-all 
      Report all unresolved symbols. This is the default. 

     ignore-in-object-files 
      Report unresolved symbols that are contained in shared 
      libraries, but ignore them if they come from regular object 
      files. 

     ignore-in-shared-libs 
      Report unresolved symbols that come from regular object 
      files, but ignore them if they come from shared libraries. This 
      can be useful when creating a dynamic binary and it is known 
      that all the shared libraries that it should be referencing 
      are included on the linker's command line. 

自分で共有ライブラリのための行動もで を制御することができます:メソッドのための4つの 可能な値があります。

通常、リンカーは 未解決のシンボルが報告されたときにエラーメッセージを生成しますが、--warn-unresolved-symbolsオプションを使用すると、警告に変更されます。

3

関数のプロトタイプを使用する前に宣言すると、関数がコンパイルされます。とにかく、リンク中のエラーは残ります。 function()が呼び出されない場合

void made_up_function_name(); 
void function() 
{ 
    made_up_function_name(); 
    return; 
} 
+0

これを反映するように編集された質問:例に示されているコールライン以外の、作成された機能には他の言及は全くありません。 – STenyaK

1

、それが実行可能ファイルに含まれていない可能性がありますし、そこから呼び出される関数は、どちらかのために検索されません。

+0

したがって、プロトタイプを宣言せずにコンパイルしてからリンクすることもできますか?私は少なくともプロトタイプを宣言しなければならないと思っています。それ以外の場合、解析エラーが発生します。 – Heisenbug

+0

@ 0verbose - 使用するC標準に依存します。もともと、プロトタイプは必要ありませんでした。そして、後でint以外のパラメータ型があった場合のみ。 –

0

そして、GCCに渡される-Dフラグが付いています。

$cat undefined.c 
void function() 
{ 
    made_up_function_name(); 
    return; 
} 


int main(){ 
} 

$gcc undefined.c -Dmade_up_function_name=atexit 
$ 

made_up_function_nameの定義を探してみてください。まだコード内に「何か」はありません。 私はこの正確なことをコードで行う良い理由は考えられません。

-Dフラグは、コンパイル時にコードを変更するための強力なツールです。

+0

'-D'フラグは、* compile *時にコードを変更します。リンク時に '-Wl、-wrap'のようなものがあります。 –

+0

'-D'とプリプロセッサのトークンマージを組み合わせた場合、' made_up_function_name'というテキストは、makefileやビルドスクリプトのいずれかに現れる必要はありません。 –

2

TL; DRそれ文句を言うことはできませんが、はそれを望んでいない。リンカーに問題を無視させると、コードがクラッシュします。それは逆効果だ。

あなたのコードは古代のC(C99より前の)関数が暗黙的に使用時に宣言されることを前提としています。 。リンカは当然コンパイルfunction()が含まれているオブジェクトファイルがどこにも見つかりませんでしたシンボルを参照すると文句を言い

void function() 
{ 
    int made_up_function_name(...); // The implicit declaration 

    made_up_function_name(); // Call the function 
    return; 
} 

:あなたのコードは、次のコードに意味的に等価ですの実装を提供するか、無意味な電話を削除して修正する必要があります。それがすべてです。リンカーの操作は必要ありません。

0

POSIXリンカが動作する「標準」アルゴリズムは、コードがコンパイルされ、エラーなしでリンクされる可能性を残します。詳細についてはこちらを参照してください:https://stackoverflow.com/a/11894098/187690

functionf.oとしましょう)を含むオブジェクトファイルをライブラリに配置する必要があります。そのライブラリはコンパイラ(および/またはリンカー)のコマンドラインに記述する必要がありますが、その時点ではコマンドラインで前述したオブジェクトファイルはfunctionやその他の関数(f.o)には呼び出されていないはずです。このような状況では、リンカーはライブラリからf.oを検索する理由を見ません。リンカーはf.oを完全に無視し、functionを完全に無視するので、made_up_function_nameの呼び出しを完全に無視します。 made_up_function_nameがどこにも定義されていなくても、コードはコンパイルされます。

1

リンカーフラグ-rまたは--relocatableを使用してビルドすると、「未定義の参照」リンクエラーメッセージも生成されません。

これは、-rが、後でリンクする新しいオブジェクトファイル内の異なるオブジェクトをリンクするためです。

関連する問題