当我碰到一些我认为会给我链接器错误但没有的错误时,我正在阅读c ++链接器教程并使用一些函数调用。
我正在使用LLVM版本10在MacOS上进行编译
❯ c++ --version
Apple LLVM version 10.0.0 (clang-1000.10.44.4)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
我有2个cpp文件,log.cpp
:
#include <iostream>
void Log(const char* message)
{
std::cout << message << std::endl;
}
和math.cpp
:
#include <iostream>
int Log(const char* message);
int Multiply(int a, int b)
{
int res = Log("Multiply");
std::cout << "Got res: " << res << std::endl;
return a * b;
}
int main()
{
std::cout << Multiply(5, 8) << std::endl;
}
在math.cpp
中,我故意声明Log
函数的返回类型不匹配。我希望可以编译它,但随后无法链接,但实际上它可以正常运行。我什至保存了返回值并打印出来以用于娱乐,这是按预期进行的垃圾处理,因为Log
函数不返回任何内容。
/tmp
❯ c++ math.cpp log.cpp -o math
/tmp
❯ ./math
Multiply
Got res: -2002196896
40
我通过转储程序集并查看正在生成的功能符号走了一步:
/tmp
❯ c++ -S math.cpp log.cpp
/tmp
❯ ls -l *.s
-rw-r--r-- 1 rsahae wheel 31924 Jun 9 11:38 log.s
-rw-r--r-- 1 rsahae wheel 32022 Jun 9 11:38 math.s
/tmp
❯ grep Log log.s math.s
log.s: .globl __Z3LogPKc ## -- Begin function _Z3LogPKc
log.s:__Z3LogPKc: ## @_Z3LogPKc
math.s: callq __Z3LogPKc
所以现在我明白了为什么链接器不给出错误,因为即使方法签名不同,符号也看起来是相同的。
我在互联网上四处张望,但找不到明确告诉我这种行为发生原因的帖子。
我尝试了返回类型(浮点型和字符串型)的其他变体,它们仍然生成相同的符号。我还尝试过更改显然会产生不同符号的参数,并因此产生了预期的错误。
对于编译器为何将具有不同签名(具有返回类型)的这两个声明编译到同一符号中的问题,有人可以帮我解释或指向文档吗?