c - 如何跟踪全局变量重新定义问题的链接器问题

我试图找出下面代码的问题,需要知道链接器如何能够跟踪下面程序中的全局变量多重定义问题,我不太清楚链接器如何在内部执行检查,所以请求帮助澄清。

**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.ohello2.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/

相关文章:

csv - 如何使用 bash 中的 awk 删除具有相似数据的行以仅保留特定列(tsv 文件)中的

c++ - 如何保证使用编译时常量初始化堆栈变量

go - 我应该如何使用 protoc-gen-go-grpc?

r - 如何根据特定行的比较来消除变量

html - 使用圆形元素的饼图

r - 如何通过合并 csv 文件创建数据框,然后基于它创建 Shiny 的应用程序?

c++ - 如何检查两个数组或列表是否相同?

reactjs - 为什么箭头函数可以工作但常规函数不能 React JS

python - 如何阻止 Selenium 在执行期间关闭驱动程序?

java - 为什么 Minecraft Forge 有这些奇怪的变量名?