Undefined symbols for architecture x86_64:
这里是说链接器找不到符号的定义。代码改改就好,但实际上整个编译链接的过程可以了解一下。
1 void test(); 2 3 int main(int argc, char **argv) { 4 test(); 5 return 0; 6 }
编译:
gcc -c -g a.c
得到a.o目标文件,看看编译后的代码段:
objdump -S a.o
1 a.o: file format Mach-O 64-bit x86-64 2 3 Disassembly of section __TEXT,__text: 4 _main: 5 ; int main(int argc, char **argv) { 6 0: 55 pushq %rbp 7 1: 48 89 e5 movq %rsp, %rbp 8 4: 48 83 ec 10 subq $16, %rsp 9 8: c7 45 fc 00 00 00 00 movl $0, -4(%rbp) 10 f: 89 7d f8 movl %edi, -8(%rbp) 11 12: 48 89 75 f0 movq %rsi, -16(%rbp) 12 ; test(); 13 16: b0 00 movb $0, %al 14 18: e8 00 00 00 00 callq 0 <_main+0x1d> 15 1d: 31 c0 xorl %eax, %eax 16 ; return 0; 17 1f: 48 83 c4 10 addq $16, %rsp 18 23: 5d popq %rbp 19 24: c3 retq
可以看到对应test的调用指令为:
e8 00 00 00 00
由于a.c里没有对test进行定义,所以编译器只能暂且将test的地址用00 00 00 00来代替,同时将这个需要重定位的地方记录在a.o的重定位表里:
➜ ld_test objdump -r a.o a.o: file format Mach-O 64-bit x86-64 RELOCATION RECORDS FOR [__text]: 0000000000000019 X86_64_RELOC_BRANCH _test
假如说最终链接的时候还是找不到该符号的定义,自然就报最开始那个错误提示了。而如果在另外的模块里有定义这个test,那链接器自然就能以正确的地址替换那个00 00 00 00了。
对了,这里只说静态链接,动态链接会更复杂一些。