web-dev-qa-db-ja.com

インライン関数を呼び出すときの未定義の参照

GCC 4.8.1でインライン関数を使用すると、本当に奇妙なエラーが発生します。

debug.hのヘッダーファイル(error.hおよびsrc/include/)に定義されている2つのほぼ同一のインライン関数がありますが、1つはメッセージのDEBUG:のプレフィックス、もう1つは%s: error: %s(プログラム名、エラーメッセージ)です。関数をインラインで定義し、デバッグビルドをコンパイルすると(マクロDEBUG=1が設定されます)、未定義の参照エラーが大量に発生します。

src/main_debug.o
  gcc -osrc/main_debug.o src/main.c -c -Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g -DCC="\"gcc\"" -DCFLAGS="\"-Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g\"" -DDEBUG=1 -DBTCWATCH_VERSION="\"0.0.1\""

src/lib/btcapi_debug.o
  gcc -osrc/lib/btcapi_debug.o src/lib/btcapi.c -c -Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g -DCC="\"gcc\"" -DCFLAGS="\"-Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g\"" -DDEBUG=1

src/lib/libbtcapi_debug.a
  ar rc src/lib/libbtcapi_debug.a src/lib/btcapi_debug.o
  ranlib src/lib/libbtcapi_debug.a

src/lib/cmdlineutils_debug.o
  gcc -o src/lib/cmdlineutils_debug.o src/lib/cmdlineutils.c -c -Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g -DCC="\"gcc\"" -DCFLAGS="\"-Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g\"" -DDEBUG=1

src/lib/libcmdlineutils_debug.a
  ar rc src/lib/libcmdlineutils_debug.a src/lib/cmdlineutils_debug.o
  ranlib src/lib/libcmdlineutils_debug.a

debug
  gcc -obtcwatch-debug src/main_debug.o -Lsrc/lib/ -lbtcapi_debug -lcmdlineutils_debug -lcurl  -ljansson 
src/main_debug.o: In function `main':
/home/marcoms/btcwatch/src/main.c:148: undefined reference to `debug'
src/main_debug.o:/home/marcoms/btcwatch/src/main.c:185: more undefined references to `debug' follow
collect2: error: ld returned 1 exit status
make: *** [debug] Error 1

ただし、debug()の定義をstatic inlineに変更すると、エラーが削除されます。しかし、その定義はstatic inlineではなくinlineですが、error()の定義からエラーを受け取ったことはありません。

定義はすべてヘッダーにあります(つまり、プロトタイプではありません)

43

マニュアル によると、-std=gnu11を渡すと、GNUインラインセマンティクスの代わりにC99が有効になります。

つまり、inlinestatic inline、およびextern inlineはすべて異なる動作をします。特に、inlineは、別の翻訳単位の外部定義を想定しています(定義を複製せずに提供できます- this answer を参照)。

45
Christoph