我试图找出下面代码的问题,需要知道链接器如何能够跟踪下面程序中的全局变量多重定义问题,我不太清楚链接器如何在内部执行检查,所以请求帮助澄清。
**hello.h**
#ifndef __HELLO_
#define __HELLO_
static int s = 20;
int g = 10;
#endif
**cat hello1.c**
#include <stdio.h>
#include "hello.h"
//int g = 10;
int main()
{
g++;
s++;
printf("g : %d s : %d\n", g, s);
function();
return 0;
}
**cat hello2.c**
#include <stdio.h>
#include "hello.h"
//extern int g;
void function()
{
g++;
s++;
printf("g : %d s : %d\n", g, s);
}
**gcc -save-temps hello1.c hello2.c -o hello**
hello2.o:(.data+0x4): multiple definition of `g'
hello1.o:(.data+0x4): first defined here
**collect2: error: ld returned 1 exit status**
我不需要修复这个错误的解决方案,我知道上面的程序会像上面那样抛出 g 的多个定义错误,但是任何人都可以解释一下它是如何在链接阶段跟踪这个错误的?。
这里是汇编代码的输出。
**cat hello1.s**
.file "hello1.c"
.data
.align 4
.type s, @object
.size s, 4
s:
.long 20
.globl g
.align 4
.type g, @object
.size g, 4
g:
.long 10
.section .rodata
.LC0:
.string "g : %d s : %d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl g(%rip), %eax
addl $1, %eax
movl %eax, g(%rip)
movl s(%rip), %eax
addl $1, %eax
movl %eax, s(%rip)
movl s(%rip), %edx
movl g(%rip), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
call function
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)"
.section .note.GNU-stack,"",@progbits
**cat hello2.s**
.file "hello2.c"
.data
.align 4
.type s, @object
.size s, 4
s:
.long 20
.globl g
.align 4
.type g, @object
.size g, 4
g:
.long 10
.section .rodata
.LC0:
.string "g : %d s : %d\n"
.text
.globl function
.type function, @function
function:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl g(%rip), %eax
addl $1, %eax
movl %eax, g(%rip)
movl s(%rip), %eax
addl $1, %eax
movl %eax, s(%rip)
movl s(%rip), %edx
movl g(%rip), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size function, .-function
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)"
.section .note.GNU-stack,"",@progbits
如果此查询之前已发布,无法跟踪类似链接,请与我分享引用。
最佳答案
内部编译器生成两个不同的目标文件 hello1.o
和 hello2.o
。它们每个都导出变量 g
:
$ readelf -sW hello1.o | grep GLOBAL
8: 0000000000000000 4 OBJECT GLOBAL DEFAULT 2 g
$ readelf -sW hello2.o | grep GLOBAL
10: 0000000000000000 4 OBJECT GLOBAL DEFAULT 2 g
链接器在为可执行文件构建全局符号表时检测到 g
的定义不止一个,并报告错误。
https://stackoverflow.com/questions/70631905/