Ответ 1
Сообщение действительно очень плохое, но это не ошибка.
Проблема здесь возникает с встроенной функцией foo()
и происходит потому, что функции Inline должны быть определены в каждом контексте перевода, где они использовались. В этой мы можем прочитать атрибут раздела:
"... инициализированные переменные ориентировочно входят в общий (или bss) раздел и могут быть размножены" . Использование атрибута раздела изменяет, в какой раздел входит переменная, и
может привести к тому, что компоновщик выдаст ошибку, если неинициализированная переменная имеет несколько определений... ".
Таким образом, когда функция foo должна быть "определена" в функции main, компоновщик находит переменную cov, ранее определенную в встроенной функции foo, и выдает ошибку.
Позволяет сделать работу перед процессором и расширять определение COV(), чтобы помочь прояснить проблему:
inline void foo()
{
do { static unsigned cov[2] __attribute__((section("cov"))) = { 40, cover() }; } while(0);
}
int main(int argc, char *argv[]) {
do { static unsigned cov[2] __attribute__((section("cov"))) = { 44, cover() }; } while(0);
if (argc > 1)
do { static unsigned cov[2] __attribute__((section("cov"))) = { 47, cover() }; } while(0);
if (argc > 2)
foo();
Чтобы облегчить рассуждение, измените атрибут раздела определения в foo встроенной функции на cov.2, чтобы скомпилировать код. Теперь у нас есть ошибка, поэтому мы можем проверить объект (.o) с помощью objdump:
objdump -C -t -j cov ./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o
./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l d cov 0000000000000000 cov
0000000000000000 l O cov 0000000000000008 main::cov
0000000000000008 l O cov 0000000000000008 main::cov
objdump -C -t -j cov.2 ./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o
./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l d cov.2 0000000000000000 cov.2
0000000000000000 u O cov.2 0000000000000008 foo()::cov
Мы видим, что компилятор делает foo:: cov, в разделе cov.2 GLOBAL (подписанный буквой u). Когда мы используем одно и то же имя раздела (cov), компилятор, пытающийся "определить foo в главном блоке, встречает предыдущий глобально определенный cov и вызывает ошибку.
Если вы сделаете inline foo static (inline static void foo()
...), что позволяет компилятору испускать код для встроенной функции и просто копирует его во время расширения, вы увидите, что ошибка исчезает, потому что нет глобального foo::. сОУ