2016-12-19 17 views
-2

最近、gcc 6.2.1コンパイラを入手して、debianテストをアップグレードした後でコードのコンパイルに問題が発生しました。gccが-O2のない関数をインライン化できない

inline int func(void) { 
    return 0; 
} 

int main (int argc, char **argv) { 
    func(); 
} 

コードは次のようにないコンパイルん:私はこの単純な例にそれを煮詰めてきた

undefined reference to 'func'

:それはで失敗

gcc -o exec code.C# gcc 6.2.1

同じホスト上でgcc 4.8、4.9、5で試して失敗しました。 それは私が追加した場合、コンパイルん:

gcc -o exec code.c -O2 # gcc 6.2.1

を、私はそれが-O2フラグではなくせずに動作します理由として、本当に興味が、私はこれが動作するように期待しますか?

+6

「コードは*コンパイルしない*」*とはどういう意味ですか?どのようなエラーが出ますか?あなたの質問を編集して、コンパイラからの完全で完全な編集されていない出力を含めてください。 –

+1

インラインで何回繰り返す必要がありますか...真剣に... – DeiDei

+2

'func'の' return'文がないので、あなたのプログラムはコンパイルされません。関数。コンパイラからのエラーメッセージはかなり明確です。 –

答えて

1

コンパイラコマンドに "-O"オプションを追加する。インライン展開は、最適化が有効な場合にのみオンになります。

C99インライン関数デフォルト

がインラインキーワードの標準C99セマンティクスを使用するように、クランは、GNU C11モードでCコードを構築します。これらのセマンティクスはGNU C89モードのものとは異なります。これは5.0より前のバージョンのGCCのデフォルトモードです。たとえば、次のコードを考えてみます。

C99で
inline int add(int i, int j) { return i + j; } 

int main() { 
    int i = add(4, 5); 
    return i; 
} 

は、インライン関数の定義が唯一のインライン化のために提供されていることを意味し、プログラム内のどこか(インラインなし)別の定義が存在していること。これは、このプログラムが不完全であることを意味します。なぜなら、addがインライン化されていないと(例えば、最適化せずにコンパイルするとき)、mainはその他の定義への未解決の参照を持つからです。したがって、我々はこのように(正しい)リンク時にエラーが発生します。これとは対照的に

Undefined symbols: 
    "_add", referenced from: 
     _main in cc-y1jXIr.o 

は、(GCCの古いバージョンではデフォルトで使用される)GNU C89モードでC89標準プラス機能がたくさんあります。 C89にはインラインキーワードはありませんが、GCCはこれを拡張機能として認識し、オプティマイザのヒントとして扱います。

この問題を解決するには、いくつかの方法があります。

  1. 変更は、静的なインライン関数に追加します。これは通常、翻訳ユニットが1つだけ機能を使用する必要がある場合に適切なソリューションです。静的インライン関数は常に翻訳単位内で解決されるため、プログラム内の別の場所で関数の非インライン定義を追加する必要はありません。
  2. addのこの定義からインラインキーワードを削除します。 inlineキーワードは、関数がインライン化されるのに必要ではなく、それが保証されるわけでもありません。一部のコンパイラは完全にそれを無視します。 Clangはそれをプログラマからの軽度の提案として扱います。
  3. プログラムのどこか他の場所にaddの外部(非インライン)定義を提供します。 2つの定義は同等でなければなりません!
  4. GNU C89の方言で、-std = gnu89をClangオプションのセットに追加してコンパイルします。このオプションは、プログラムソースを変更できない場合、またはプログラムが変更できない追加のC89固有の動作にも依存している場合にのみ推奨されます。

これはすべてCコードにのみ適用されます。 C++のインラインの意味は、GNU89またはC99の意味とは大きく異なります。

+0

OPはclangではなくgccでコンパイルされています。 – frasnian

+0

私は説明に感謝します:)。インラインはc99以降ではスタンドアロンではないことに気づきませんでした。 「インライン追加」機能と衝突する「追加」機能を追加せずに、どのように外部の非インラインを提供しますか? –

関連する問題