24

OS X 10.8でXCode 4.5.1を使ってサンプルコード「SonofGrab」をコンパイルしようとしています。

controller.m で 1 つの関数が次のように定義されています。

inline uint32_t ChangeBits(uint32_t currentBits, uint32_t flagsToChange, BOOL setFlags);

これにより、次のエラー メッセージが表示されます。

Undefined symbols for architecture x86_64:
"_ChangeBits", referenced from:
-[Controller awakeFromNib] in Controller.o
[...]
ld: symbol(s) not found for architecture x86_64

関数 ChangeBits のインライン化を削除すると問題は解決しますが、リンカが元の定義の Changebits を見つけられないのはなぜですか?

4

1 に答える 1

43

それは私には、バグのように見えます。この単純なケースでは、同じエラーが発生します。

inline void foo() {}
int main() {
    foo();
}

収量:

$ clang test-inline.c
Undefined symbols for architecture x86_64:
  "_foo", referenced from:
      _main in test-inline-MfUY0X.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

それは間違っているに違いない!? について何かが完全に欠けていない限りinline

編集:ああ、待って、これをチェックしてください - http://clang.llvm.org/compatibility.html#inline

inline基本的に、私も完全には理解していなかったようです。そして、Apple でそのサンプル コードを書いた人もそうではありませんでした。

関数のinlineon はChangeBits、その定義がインライン化にのみ使用されることを意味します。関数を常にインライン化する必要があるわけではありません。アプリケーションの他の場所で利用可能な別の非インライン定義が必要です。そうでない場合は違法です。したがって、非インラインChangeBitsが提供されていないため、リンクエラーが発生します。

本当の解決策は、定義がその翻訳単位に対してのみローカルであり、したがって非インライン定義が存在する必要がないことをコンパイラに伝えるので、ChangeBitsasを宣言することです。static inline

ただし、リンク先の LLVM ページの詳細については、こちらを参照してください。それが役立つことを願っています!

于 2012-10-11T17:49:38.397 に答える