Я провел несколько дней в странной проблеме и наконец обнаружил, что в проекте были две встроенные
функции с одной и той же сигнатурой, и они вызвали проблему. Для упрощения ситуации приведем пример: два файла 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();
}
Обратите внимание, что встроенные
функции 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
.
Мой вопрос в том, что независимо от результата или того, как выполняется компиляция, нет ошибок или даже предупреждений о том, что я определил встроенные
функции несколько раз. Что, черт возьми, происходит с компилятором и компоновщиком в такой ситуации?
РЕДАКТИРОВАТЬ:
Взгляните на символы в объектном файле
nm a.o b.o | c++filt
Оба файла имеют запись echo ()
. Так что я думаю, что проблема возникает во время ссылки. Можно ли сказать, что компоновщик случайным образом выбирает одну реализацию и отбрасывает все остальные?