这个问题出现在这个问题的背景下:找到未执行的c ++代码行
在搜索此问题时,大多数人都试图将代码和变量添加到同一部分中 - 但这绝对不是问题所在.这是一个最小的工作示例:
unsigned cover() { return 0; }
#define COV() do { static unsigned cov[2] __attribute__((section("cov"))) = { __LINE__, cover() }; } while(0)
inline void foo() {
COV();
}
int main(int argc, char* argv[])
{
COV();
if (argc > 1)
COV();
if (argc > 2)
foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果与g++ -std=c++11 test.cpp
(g ++(GCC)4.9.2 20150212(Red Hat 4.9.2-6))出现以下错误:
test.cpp:6:23: error: cov causes a section type conflict with cov
COV();
^
test.cpp:11:30: note: ‘cov’ was declared here
COV();
^
Run Code Online (Sandbox Code Playgroud)
但错误并不是很有用,因为它没有说明为什么这应该是冲突..ii和.s临时文件都没有提供可能是什么问题的提示.实际上.s文件中只有一个节定义
.section cov,"aw",@progbits
Run Code Online (Sandbox Code Playgroud)
我不明白为什么下一个定义应与此冲突("aw",@ progbits是正确的......).
有没有办法获得更多相关信息?看看确切的冲突是什么?或者这只是一个错误......?
小智 1
该消息确实非常糟糕,但它不是一个错误。\n这里的问题发生在内联函数 foo()\n 上,因为内联函数必须在它们使用的每个翻译上下文中定义。在此链接中,我们可以阅读有关节属性的信息:\n
“..未初始化的变量暂时进入公共(或 bss)节,并且可以乘以 \xe2\x80\x98define\xe2\x80\x99。使用节属性会更改什么如果未初始化的变量有多个定义,则变量进入的部分和\n可能会导致链接器发出错误...”。
因此,当需要在 main 函数中“定义” foo 函数时,链接器会找到先前在内联函数 foo 中定义的 cov 变量并发出错误。
\n\n让 xe2x80x99s 使预处理器工作并扩展 COV() 定义以帮助澄清问题:
\n\ninline void foo()\n{\n do { static unsigned cov[2] __attribute__((section("cov"))) = { 40, cover() }; } while(0);\n}\n\nint main(int argc, char *argv[]) {\n do { static unsigned cov[2] __attribute__((section("cov"))) = { 44, cover() }; } while(0);\n\n if (argc > 1)\n do { static unsigned cov[2] __attribute__((section("cov"))) = { 47, cover() }; } while(0);\n\n if (argc > 2)\n foo();\n
Run Code Online (Sandbox Code Playgroud)\n\n为了方便推理,让\xe2\x80\x99s将foo内联函数中定义的section属性修改为cov.2,以便编译代码。现在我们没有\xe2\x80\x99t错误,因此我们可以使用objdump检查对象(.o):
\n\nobjdump -C -t -j cov ./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o\n\n./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o: file format elf64-x86-64\n\nSYMBOL TABLE:\n0000000000000000 l d cov 0000000000000000 cov\n0000000000000000 l O cov 0000000000000008 main::cov\n0000000000000008 l O cov 0000000000000008 main::cov\n\nobjdump -C -t -j cov.2 ./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o \n\n./cmake-build-debug/CMakeFiles/stkovf.dir/main.cpp.o: file format elf64-x86-64\n\nSYMBOL TABLE:\n0000000000000000 l d cov.2 0000000000000000 cov.2\n0000000000000000 u O cov.2 0000000000000008 foo()::cov\n
Run Code Online (Sandbox Code Playgroud)\n\n我们可以看到编译器将foo::cov,在 cov.2 节中设为 GLOBAL (由 \xe2\x80\x98u\xe2\x80\x99 字母签名)。\n当我们使用相同的节名称 (cov) 时,编译器,尝试在主块中 \xe2\x80\x98define\xe2\x80\x99 foo 遇到先前全局定义的 cov 并发出错误。
\n\n如果您将内联 foo 设为静态(inline static void foo()
. . .),这可以避免编译器为内联函数发出代码并仅在扩展时复制它,您\xe2\x80\x99将看到错误消失,因为没有全局 foo: :cov。