【问题标题】:Linker is unable to tell the difference between function and variables?链接器无法区分函数和变量?
【发布时间】:2020-08-30 01:31:29
【问题描述】:

下面是我的代码:

//Module 1
void sth()
{
}
//Module 2

int sth= 1;
int func()
{
}

并且在调用gcc 时,链接器会抛出错误:

找到了多个定义。

但是链接是愚蠢的,它无法区分函数和变量之间的区别吗?特别是ELF中有一个符号表,Elf64_Symbol中有一个“类型”来区分函数和对象。为什么链接器不使用这些信息?

【问题讨论】:

  • 不要诽谤链接器。 1)我怀疑 main 可以用作变量。在我看来,它是一种受限制的关键字。 2) 你有 multiple-defined main,GCC 是对的。首先,您将其定义为 void 函数,然后再次将其定义为 int !
  • @A P Jo 我已更改名称以更好地解决问题。同样,我不得不说在 C#、Java 等高级语言中没有这样的问题,而且对我来说很奇怪的是链接器无法区分函数和对象。
  • C# 和 Java 未编译为机器码。他们有自己的虚拟机/口译员。你可以在那里做多个这样的定义,因为一个复杂的环境“支持”你的代码在那里执行它,并且可以在你不知道的情况下实现各种诡计。但是当编译成二进制时,它会在 金属上运行,如果没有技巧,这是不合法的。
  • @APJo — 你可以使用main 作为局部变量来拥有int foo(void) { int main = 1; printf("%d\n", main++); return ++main; }。你不能有一个名为 main 的全局变量。
  • 链接器作用于名字——而且只作用于名字。名称所代表的对象的类型不是物质的。您必须使用名为 sth 的不同对象 - 您不允许这样做(并且链接器会抱怨)。如果您在一个文件中使用extern int sth; 并在该文件中使用sth 作为int,然后在另一个文件中使用sth 函数,那么生活会变得更加复杂。然而,这是未定义的行为——除了不快乐,没有什么是可以保证的。

标签: c gcc linker


【解决方案1】:

您为链接器提供了多个定义。

符号sth在两个模块中定义,一个是int,一个是void函数。如果相同的符号出现在多个目标文件中,无论类型如何,如果您尝试将它们链接在一起,链接器都会抛出错误。

一个符号只能在一个目标文件中定义。如果您想在其他文件中使用它,您可以在其他文件中声明它,但是声明必须与定义匹配。

或者,如果您希望特定符号仅在定义它的文件中可见,而在其他文件中不可见,则需要向其添加 static 存储类说明符。

【讨论】:

  • 感谢您的回答,我其实知道它为什么会抛出错误,但不明白为什么链接器不是为了区分函数和对象而设计的,正如我在帖子中提到的,实现将是一个非常简单的在符号表中查找。
  • @amjad 在一个文件中你说这是一回事,在另一个文件中你说这是另一回事。那么链接器应该选择哪一个?即使两者都被定义为相同的类型,您仍然会得到相同的错误。
  • @amjad 如果您希望所讨论的符号仅在该文件中是本地的并且在其他文件中不可见,则需要将其标记为static
  • @amjad:那么,当您使用 dlsym 在 dso 中查找符号时,您认为应该返回哪些竞争符号?
猜你喜欢
  • 2012-01-24
  • 2011-12-26
  • 1970-01-01
  • 1970-01-01
  • 2021-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-17
相关资源
最近更新 更多