gpt4 book ai didi

c - Linux 中 gcc 链接期间的多个定义错误

转载 作者:行者123 更新时间:2023-12-05 03:37:25 26 4
gpt4 key购买 nike

最近开始在 Linux 上进行 C 编码并遇到“多重定义”错误(来源 A.cB.c 如下)

gcc -Wall A.o B.o -o C

/usr/bin/ld: B.o: in function "Hello":
B.c:(.text+0x0): multipledefinition of `Hello'; A.o:A.c:(.text+0x0): first defined here

通过 S.O 搜索,建议使用此链接器命令行选项

--allow-multiple-definition (-z muldefs)
Normally when a symbol is defined multiple times, the linker will report a fatalerror.
These options allow multiple definitions and the firstdefinition will be used.

运行这条命令绕过了错误信息

gcc -Wall -Wl,--allow-multiple-definition A.o B.o -o C

似乎恢复了平静,然而,它输出

./C

Hello A
Hello A
World B

我期待下面的输出并“假设”链接器会顺利解决任何符号冲突,但至少保留现有代码功能

Hello A
Hello B
World B

但是,生成的 C ELF 二进制文件通过检查来自objdump -S -M intel C

  • 删除了 B.c
  • 中重复的 Hello()
  • A.c
  • 中重新指向对 Hello() 的任何调用

问题

  1. 重命名符号 Hello() 是唯一正确的解决方案吗?
  2. 使用--allow-multiple-definition 选项是不好的做法吗?
  3. 如果可能的话,链接器是否应该对预期代码更敏感通过限制函数可见性来实现功能,即理解 Hello() 是 B.o 中的重复符号,从 World() 调用它应该限制在 B.o 而不是查看 < strong>A.o?



gcc -Wall -c A.c

#include <stdio.h>

void Hello(void)
{
printf("Hello A\n");
}

int main()
{
Hello();
World();

return 0;
}

gcc -Wall -c B.c

#include <stdio.h>

void Hello(void)
{
printf("Hello B\n");
}

void World(void)
{
Hello();
printf("World B\n");
}

已编辑

根据评论/答案,添加静态关键字效果很好

static void Hello(void)
{
printf("Hello B\n");
}

现在不需要使用那个命令行选项

gcc -Wall A.o B.o -o C

Hello A
Hello B
World B

这个问题的真正插入力是我们构建了一个 UASM 程序集对象文件,并给出了有关 C static 关键字的提示,至少我现在可以研究 UASM 中可用的内容来使这些函数对对象私有(private)。

更新

对于UASM,能够通过添加将函数范围限制在目标文件中

PROC PRIVATE FRAME

谢谢!

最佳答案

  1. 最好更改名称,但您也可以将它们设为静态(以限制对其所在文件的访问)或稍微更改签名。

  2. 是的。令人难以置信的糟糕!在现实世界中,您期望 Hello() 做某事,但现在您让编译器决定使用哪个版本的 Hello() - 可能是正确的。可能是错误的。甚至有这个选项(恕我直言)真是太疯狂了。

  3. 您可以通过将它们设为静态来做到这一点。

这有点学术性。为什么您首先认为拥有 2 个名为 Hello() 的全局作用域函数是个好主意?

关于c - Linux 中 gcc 链接期间的多个定义错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69326932/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com