为什么重新定义动态或静态库中已存在的函数不会引发任何错误?

时间:2014-06-24 15:11:52

标签: c linker-errors duplicate-symbol

对动态库中已存在的函数的Wy重新定义不会抛出任何编译和链接错误吗?

在以下功能中

#include "calc_mean.h"
#include <stdio.h>

int mean(int t, int v) {
  return 0;
}

int main () {
  int theMean = mean(3,6);
  printf("\n  %d\n",theMean);
}

共享库内部平均功能的定义已经如下所示。

#include <stdio.h>
#include "calc_mean.h"

int mean(int a, int b) {
  return (a+b)/2;
}

均值函数的定义已存在于共享库libmean.so中。但在编译期间,我没有看到任何重新定义错误,编译成功。

在成功执行时,我看到的o / p是0而不是4,因此共享库中的mean函数定义没有被执行,但主模块中的函数定义正在执行。

为什么会这样?

3 个答案:

答案 0 :(得分:5)

如果在编译/链接过程中尚未找到该函数,则链接器仅链接函数库中的函数。

功能差异的原因是存在不同类型的符号。库函数是一个弱符号。仅在尚未定义时才包括它。 nm是用于在对象或可执行文件中列出符号的工具。在其manpage中,您可以找到符号类型的列表。

weak symbols上还有一个维基百科页面。

答案 1 :(得分:1)

对一个外部可见函数的两个定义(即使定义相同,对于非内联函数)会导致未定义的行为,无需诊断。 (参考:C99 6.9#5及附件J.2)

在C中,某些非法代码需要编译器诊断,而有些则不需要。通常,那些不需要诊断的是:

  • 要求所有编译器检测并报告错误将被视为太过于禁止
  • 现有使用的系统没有对其进行诊断,标准委员会不希望现有的实施方案不符合要求。

在这种情况下,我的猜测是这是第一个案例;他们希望保留编译器/链接器的选项,以实现弱符号作为扩展,因此他们没有指定编译器必须在此处发出警告。或者通常很难检测到这一点,我从未尝试过编写链接器!

如果没有给出诊断,应将其视为实施质量问题。也许可以将不同的标志传递给链接器,以便拒绝此代码;如果没有,那么您可以提交错误报告或功能请求。

答案 2 :(得分:-1)

您是否正确链接了共享库,因为编译器应该提供错误:

&#39; mean&#39;

的多重定义