我花了几天时间解决一个奇怪的问题,最后发现inline
项目中有两个相同签名的函数,它们导致了问题。为了简化情况,这里举个例子:两个cpp文件:
a.cpp
#include <iostream>
void b();
inline void echo()
{
std::cout << 0 << std::endl;
}
int main()
{
echo();
b();
return 0;
}
和 b.cpp
#include <iostream>
inline void echo()
{
std::cout << 1 << std::endl;
}
void b()
{
echo();
}
请注意,inline
函数echo
具有相同的签名但不同的实现。编译运行
g++ a.cpp b.cpp -o a.out && ./a.out
或者像这样
g++ a.cpp -c
g++ b.cpp -c
g++ a.o b.o -o a.out
./a.out
它打印0 0
。(我为此使用了 g++ 4.6.1,并使用 clang++ 2.9 进行了测试,结果相同)
如果打开优化就不会发生这种情况,比如
g++ -O3 a.cpp b.cpp -o a.out && ./a.out
就是0 1
这个时候。
我的问题是,无论结果或编译如何执行,都没有关于我多次定义inline
函数的错误甚至警告。在这种情况下,编译器和链接器到底会发生什么?
编辑:
查看目标文件中的符号
nm a.o b.o | c++filt
两个文件都有记录echo()
。所以我认为问题发生在链接时。是否可以说链接器随机选择一种实现并丢弃所有其他实现?