【问题标题】:Redefining functions lin libC重新定义函数 lin libC
【发布时间】:2019-03-20 01:54:18
【问题描述】:

假设以下简单的C 代码:

file1.c

#include <stdio.h>

char* gets(char* i){
  return i;
}

这是重新定义 libC 原生函数 gets

这与gcc file1.c 编译得很好。

我的问题是链接器为什么不抱怨duplicate symbols,因为这个函数也在 libC 本身中定义?

【问题讨论】:

  • 注意:gets()不在C11/C17的标准库中。
  • @chux Linker 警告warning: the gets' 功能很危险,在使用时不应使用`。我用 C11。
  • Alex,一定要试试gcc -std=c11 -Wall -Wextra -Wconversion file1.c
  • 警告是另一回事,与溢出保护有关
  • 关于gets() 的警告不是关于溢出保护,而是关于函数gets() 已经贬值多年,并在C 编程语言的最后两个版本中完全删除

标签: c libc


【解决方案1】:

因为您可以在 C 中覆盖标准库中的函数,请查看this

【讨论】:

  • 覆盖标准库函数是未定义的行为,尽管它经常(但不总是)“按预期工作”。请参阅 C 标准的 section 7.1.3 (Reserved Identifiers),尤其是第 2 段。
【解决方案2】:

在链接阶段添加选项-whole-archive,如下:

gcc -c -ofile1.o file1.c
gcc -ofile1 -Wl,--whole-archive -lc file1.o -Wl,--no-whole-archive

结果:

file1.o: In function `gets':
file1.c:(.text+0x0): multiple definition of `gets'
file1.o: In function `main':
file1.c:(.text+0x18): undefined reference to `gets@@GLIBC_2.2.5'
collect2: error: ld returned 1 exit status

【讨论】:

    【解决方案3】:

    您遇到了未定义的行为,请参阅N1570 6.9(p5) External definition

    如果使用外部链接声明的标识符用于 表达式(作为 sizeof_Alignof 的操作数的一部分除外 结果是整数常量的运算符),在整个 程序应该有一个确切的外部定义 标识符;否则,不得超过一个.161)

    可以看出。该标准允许两种可能性:

    1. 正是一个定义
    2. 不超过一个定义。

    可能依赖于libc 的链接,而libc 本身是系统相关的。如果你静态链接libc,链接器会抱怨。在动态链接的情况下,它没有理由抱怨。

    如果您查看objdump,您会发现plt 部分喜欢

    898:   e8 b3 fe ff ff          callq  750 <gets@plt>
    

    无论如何行为是未定义的。

    【讨论】:

      猜你喜欢
      • 2011-02-08
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-18
      • 2019-08-07
      相关资源
      最近更新 更多