重新定义发生在哪个程序中?编译或链接时间
redefinition happend in which procedure? compile or link time?
如果我定义了一个函数两次,我将得到一个重新定义错误消息,但是我很困惑,重新定义发生在编译或链接时间?
和为什么你可以重写malloc在libc没有重定义错误?
当您有两个具有相同原型或签名的函数时(函数签名由函数名称,参数数量和参数类型组成,不包括返回类型),您将获得函数重定义错误。
如果编译器看到两个函数具有相同的签名,这是一个编译时错误:
int foo(int a);
double foo(int b);
为什么可以在库中重写函数调用?让我们看看如何将代码构建为可执行文件:
- 编译器被每个源文件调用并输出一个目标文件:任何无法解析的函数调用(即调用不同文件中的函数)都是一个外部符号,链接器必须解析。
- 链接器获取所有的目标文件并尝试解析所有的符号;但它是以先到先得的方式做到这一点的。对于外部符号,它将考虑它找到的第一个定义,而不担心同一符号可能有更多的定义。
所以,链接器实际上允许你重写函数的行为。这完全取决于文件链接的顺序——它找到的第一个函数定义就是用来解析符号的函数定义。
希望这能对这件事有所帮助。
两者皆可。它也可能来自程序员编辑源代码或修改构建脚本。
当链接器发现两个名称相同的东西(符号)时,会发出"Redefinition"错误。
链接器发现两个名称相同的符号有很多原因。一些可能性(有许多排列)包括;- 在link命令中指定对象文件两次。这通常是由于构建脚本中的错误造成的。
- 包含相同函数定义的两个对象文件。这是由代码复制造成的——例如,将函数定义复制到不同的源文件中,然后对这些源文件进行编译和链接。它也可能是由于预处理器的拙劣操作(例如,
#include
一个包含两个源文件的全局变量定义的文件)。
导致上述情况的原因通常是程序员的错误(例如,在构建脚本中提供了错误的链接器命令,滥用预处理器,在项目之间复制和粘贴代码)。
像libc这样的库中的函数经常被"覆盖"的原因是,如果链接器在目标文件中找不到符号,它通常只在库中查找符号。因此,如果一个目标文件定义了malloc()
,链接器将解析对它的所有调用,而不是尝试使用库中的版本来解析。这种事情是相当危险的,因为库中的一些其他函数(例如,甚至在libc中)可能直接解析到原始的malloc()
(例如,一些调用可能是内联的),这可能会导致不可预测的行为。这种行为也是特定于链接器的:尽管这种事情在unix/linux变体中很常见,但在某些系统中,链接器的工作方式不同。
相关文章:
- 这是使用回溯的 nqueen 问题,但我使用了动态 2d 数组,我的程序编译良好,但不返回任何输出
- C ++程序编译错误,找不到/访问文件
- C++程序编译没有问题,但无法运行
- Mongdb C++ 驱动程序编译错误 for document{}.
- 添加类型名会导致程序编译失败
- 将 C 程序更改为 C++ 程序 - 编译错误
- 程序编译,但当分解为函数时实际上不会移动电机
- 如何链接 glib-2.0 库进行 c/c++ 程序编译
- 为什么 gcc 和 clang 为我的程序编译为不同的"const"结果?
- 复数程序编译时的计算方法错误
- qt 命令行应用程序编译
- 程序编译和运行,但一段时间后,它停止使用Typedef关键字在CPP上工作
- QML应用程序编译一个 *form.ui.qml文件,但忽略了关联的.qml文件
- 为什么该程序编译但不显示任何输出
- 分割故障程序编译为共享库,但不静态
- 程序编译,但我认为开关被忽略
- 程序编译后崩溃
- 什么是程序编译中的PIC级别
- 尽管使用不存在的成员,但程序编译
- C++程序编译在 Ubuntu 中失败,但在 MacOSX 中工作