如果我定义了两次函数,我将收到重定义错误消息,但是 我很困惑重新定义发生在编译或链接时间?
为什么你可以在没有重定义错误的情况下覆盖libc中的malloc?
答案 0 :(得分:1)
如果您有两个具有相同原型或签名的函数,则会出现函数重定义错误(函数签名由参数和参数类型的函数名称编号组成,不包括返回类型)。
如果编译器看到两个具有相同签名的函数,则这是编译时错误:
int foo(int a);
double foo(int b);
为什么你可以覆盖库中的函数调用?让我们看看如何将代码构建为可执行文件:
因此,链接器实际上允许您覆盖函数的行为。这一切都取决于文件链接的顺序 - 它找到的第一个函数定义是用于解析符号的函数。
希望这能为这件事提供一些启示。
答案 1 :(得分:0)
其中之一或两者。它也可以由程序员编辑源代码或修改构建脚本产生。
当链接器找到具有相同名称的两个(符号)时,会发出“重新定义”错误。
链接器可能找到两个具有相同名称的符号的原因有很多。一些可能性(有许多排列)包括;
#include
包含两个源文件的全局变量定义的文件。)上述情况的原因通常是程序员错误(例如,在构建脚本中提供错误的链接器命令,滥用预处理器,在项目之间复制和粘贴代码。
像libc这样的库中的函数通常可以被“覆盖”的原因是,如果链接器在目标文件中找不到它们,它通常只在库中查找符号。因此,如果对象文件定义malloc()
,则链接器将解析对该对象的所有调用,而不是尝试使用库中的版本进行解析。这种事情是非常危险的,因为库中的一些其他功能(例如甚至在libc内)可以直接解析为原始malloc()
(例如,某些调用可能被内联),这可能是不可预测的行为。这种行为也是特定于链接器的:虽然这种情况在unix / linux变体中很常见,但是有些系统会让链接器做不同的事情。