Переопределение функций lin libC - PullRequest
7 голосов
/ 20 марта 2019

Допустим следующий простой C код:

file1.c

#include <stdio.h>

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

, которая переопределяет нативную функцию libC gets.

Это прекрасно компилируется с gcc file1.c.

У меня вопрос: почему компоновщик не жалуется на duplicate symbols, так как эта функция также определена в самой libC?

Ответы [ 3 ]

1 голос
/ 20 марта 2019

добавить опцию -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
1 голос
/ 20 марта 2019

Поскольку вы можете переопределить функции из стандартных библиотек в C, отметьте this

0 голосов
/ 20 марта 2019

Вы столкнулись с неопределенным поведением, см. N1570 6.9(p5) External definition:

Если в выражении используется идентификатор, объявленный с внешней связью (кроме как как часть операнда sizeof или _Alignof оператор, результатом которого является целочисленная константа), где-то во всей программе должно быть ровно одно внешнее определение для идентификатора;в противном случае их должно быть не более 161

1008

Как видно.Стандарт допускает 2 возможности:

  1. ровно одно определение
  2. не более одного определения.

Это может зависит от связи libc, которая сама зависит от системы.В случае статической ссылки libc компоновщик будет жаловаться.В случае динамического связывания нет причин жаловаться.

Если вы посмотрите на objdump, вы найдете plt раздел вроде

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

В любом случае поведение не определено.

...