回答
其中之一或两者。它也可能源于程序员编辑源代码或修改构建脚本。
当链接器找到两个具有相同名称的东西(符号)时,会发出“重新定义”错误。
链接器可能会找到两个具有相同名称的符号的原因很多。一些可能性(有许多排列)包括;
- 目标文件在链接命令中指定了两次。这通常是由构建脚本中的错误造成的。
- 两个包含相同函数定义的目标文件。这是代码复制的结果 - 例如,函数定义被复制到不同的源文件中,然后进行编译和链接。它也可能来自与预处理器的猴业务(例如
#include
ing文件包含由两个源文件定义的全局变量)。
的东西,如上述的原因通常是程序员错误(例如,在构建脚本供给坏接头命令,项目之间的预处理器,复制和粘贴代码的误用。
原因在库中的函数像libc通常可以被“重载”,就是链接器通常只在库中找到符号,如果它在对象文件中找不到它们的话,那么,如果一个目标文件定义了malloc()
,链接器将解析所有的调用,而不是尝试在库中使用版本来解析这种事情是相当危险的,因为库中的一些其他函数(例如,甚至在libc中)可能直接解析为原始的malloc()
(例如一些调用可能被内联),这可能会导致不可预知的行为。这种行为也是特定于链接器的:虽然这种情况在unix/linux变体中很常见,但有些系统中连接器的做法各不相同。
如果您有两个具有相同原型或签名的函数(函数签名由参数和参数类型的函数名称数量构成,不包含返回类型),则会得到函数重定义错误。
这是一个编译时错误,如果编译器看到两个函数具有相同签名:
int foo(int a);
double foo(int b);
为什么你可以重写库函数调用?让我们来看看代码是如何建成的可执行文件:
- 编译器被称为为每个源文件和输出的目标文件:任何函数调用不能被解析(即调用在不同文件中的函数)链接器必须解决的外部符号。
- 链接器获取所有对象文件并尝试解析所有符号;但它是以先到先得的方式完成的。对于外部符号,它会考虑它找到的第一个定义,而不用担心可能存在更多相同符号的定义。
因此,链接器实际上允许您覆盖函数的行为。这一切都取决于文件链接的顺序 - 它找到的第一个函数定义是用于解析符号的函数。
希望对此有所了解。
谢谢Pandrei, 做的“先到先得”方式只适用于共享库吗? 这里是我想要的,main.cpp调用def1.cpp和def2.cpp中定义的函数: gcc main.cpp def1.cpp def2.cpp //多重定义错误 但是 gcc main.cpp def1。所以def2.so //是的,先到先得的方式 有什么区别? –
@ SamH.W不,它不适用于图书馆;实际上链接器并不知道区别;它只接收一堆目标文件并尝试解析这些符号。试试这个:一个带有函数原型的头文件,两个源文件,每个带有它自己的实现,并在main()中调用该函数。即使您对同一个函数有两个不同的实现,也应该创建它。 – Pandrei
- 1. GTK3程序不再编译 - 链接时GCC“未定义参考”
- 2. 编译和链接bash配置脚本在哪里发生?
- 3. 当更新静态库时,主应用程序必须重新编译或重新链接?
- 4. Docker重新编译时间
- 5. Opencv源编译与cuda生成多个定义链接错误
- 6. 安装是否在运行时或编译期间发生?
- 7. 在运行时或编译/链接时绑定模块的接口要求,哪个更好?
- 8. GWT发生器得到编译时间
- 9. 链接错误“LogonUser”编译C++程序?
- 10. 无法编译链接列表程序
- 11. 在D中编译时间码生成
- 12. Idoc的自定义程序编辑并重新发布到sap
- 13. 在应用程序中链接的自定义URL链接
- 14. 如何在tomcat中运行应用程序时重新链接链接错误?
- 15. 重新编译iOS应用程序以在Apple Store上发布
- 16. 重新编译二进制文件时发生总线错误
- 17. 在编译时链接vs在运行时链接到std ::库
- 18. 编译Fortran和C++程序并从intel编译器链接
- 19. 编译时错误:多重定义“主”
- 20. 在编译时或链接时gcc的fvisibility
- 21. 如何在发生更新时重新启动应用程序?
- 22. 生成自定义编译时间警告C#
- 23. 定义变量名称,除非在编译器中重新编译
- 24. 在程序执行时重新编译代码
- 25. 链接错误:“重新定位R_X86_64_32 ...在制作共享对象时无法使用;使用-fPIC重新编译”
- 26. 使用VS编译器和链接程序生成的Windows驱动程序
- 27. 在套接字编程的select()中重新启动定时器
- 28. 什么时候在oracle中重新编译时锁定对象
- 29. 编译.exe程序时生成的.lib
- 30. 编译时Ibm MobileFirst链接程序错误
重新定义在链接阶段发生。 – Ishmeet
是的,您可以覆盖malloc(),因为如果符号尚未被您自己的代码满足,链接器只会查看libc。通用建议:除非你真的*知道你在做什么,否则不要试用。 – DevSolar