Lazy Diary @ Hatena Blog

PowerShell / Java / miscellaneous things about software development, Tips & Gochas. CC BY-SA 4.0/Apache License 2.0

undefined referenceに対するldのオプション--warn-unresolved-symbolsと--noinhibit-execの効果

/mnt/c/tmp$ cat caller.c
#include <stdio.h>
#include "callee.h"

void main(int argc, char *argv[]) {
  if (argc == 1) {
    callee();
  } else {
    printf("caller\n");
  }
}
/mnt/c/tmp$ cat callee.h
extern int callee();
/mnt/c/tmp$ cat callee.c
#include <stdio.h>

int callee() {
  printf("callee\n");
}
/mnt/c/tmp$ rm -f a.out; cc caller.c
/usr/bin/ld: /tmp/ccYSCa5B.o: in function `main':
caller.c:(.text+0x1f): undefined reference to `callee'
collect2: error: ld returned 1 exit status
/mnt/c/tmp$ rm -f a.out; cc caller.c -Wl,--warn-unresolved-symbols
/usr/bin/ld: /tmp/ccamAA53.o: in function `main':
caller.c:(.text+0x1f): warning: undefined reference to `callee'
/mnt/c/tmp$ ./a.out
Segmentation fault (core dumped)
/mnt/c/tmp$ ./a.out 1
caller
/mnt/c/tmp$ rm -f a.out; cc caller.c callee.c
/mnt/c/tmp$ ./a.out
callee
/mnt/c/tmp$ ./a.out 1
caller
/mnt/c/tmp$ rm -f a.out; cc caller.c -Wl,--noinhibit-exec
/usr/bin/ld: /tmp/cchx6K3l.o: in function `main':
caller.c:(.text+0x1f): undefined reference to `callee'
/mnt/c/tmp$ ./a.out
Segmentation fault (core dumped)
/mnt/c/tmp$ ./a.out 1
caller

externされている関数の実体がリンクされていなくてもa.outが作られる。実行時に実体がない関数が実行された時点でSegmentation faultが発生する。undefined referenceに対する効果は--warn-unresolved-symbols--noinhibit-execも同じ。

ccの戻り値も0になる。

/mnt/c/tmp$ rm -f a.out; cc caller.c -Wl,--warn-unresolved-symbols
/usr/bin/ld: /tmp/ccOTDxhY.o: in function `main':
caller.c:(.text+0x1f): warning: undefined reference to `callee'
/mnt/c/tmp$ echo $?
0
/mnt/c/tmp$ rm -f a.out; cc caller.c -Wl,--noinhibit-exec
/usr/bin/ld: /tmp/cc8PXv4q.o: in function `main':
caller.c:(.text+0x1f): undefined reference to `callee'
/mnt/c/tmp$ echo $?
0
/mnt/c/tmp$ rm -f a.out; cc caller.c
/usr/bin/ld: /tmp/cctnhmmT.o: in function `main':
caller.c:(.text+0x1f): undefined reference to `callee'
collect2: error: ld returned 1 exit status
/mnt/c/tmp$ echo $?
1

なお文法エラーがあるプログラムの場合は--warn-unresolved-symbols--noinhibit-execも通常通りコンパイルエラーとなって、実行ファイルは出力されない。

/mnt/c/tmp$ cat callee_error.c
#include <stdio.h>

int callee() {
  printf("callee %d\n", i);
}
/mnt/c/tmp$ rm -f a.out; cc caller.c callee_error.c -Wl,--warn-unresolved-symbols
callee_error.c: In function ‘callee’:
callee_error.c:4:25: error: ‘i’ undeclared (first use in this function)
    4 |   printf("callee %d\n", i);
      |                         ^
callee_error.c:4:25: note: each undeclared identifier is reported only once for each function it appears in
/mnt/c/tmp$ ./a.out
-bash: ./a.out: No such file or directory
/mnt/c/tmp$ rm -f a.out; cc caller.c callee_error.c -Wl,--noinhibit-exec
callee_error.c: In function ‘callee’:
callee_error.c:4:25: error: ‘i’ undeclared (first use in this function)
    4 |   printf("callee %d\n", i);
      |                         ^
callee_error.c:4:25: note: each undeclared identifier is reported only once for each function it appears in
/mnt/c/tmp$ ./a.out
-bash: ./a.out: No such file or directory
/mnt/c/tmp$