Я провел дни в странной проблеме и, наконец, обнаружил, что в проекте было две функции 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
функции несколько раз. Что на самом деле происходит с компилятором и компоновщиком в такой ситуации?
EDIT:
Посмотрите на символы в объектном файле
nm a.o b.o | c++filt
Оба файла имеют запись echo()
. Поэтому я думаю, что проблема возникает во время соединения. Можно ли сказать, что компоновщик случайным образом выбирает одну реализацию и отбрасывает все остальные?