Gcov符号在哪里?

67

我正在尝试使用gcov编译一个简单的应用程序,但是出现了以下链接错误:

gcc AllTests.o CuTestTest.o CuTest.o -o TestTest
AllTests.o: In function `global constructors keyed to 0_RunAllTests':
/home/p7539c/cutest/AllTests.c:26: undefined reference to `__gcov_init'
AllTests.o:(.data+0x44): undefined reference to `__gcov_merge_add'
CuTestTest.o: In function `global constructors keyed to 0_TestCuStringNew':
/home/p7539c/cutest/CuTestTest.c:30: undefined reference to `__gcov_init'
CuTestTest.o:(.data+0x64): undefined reference to `__gcov_merge_add'
CuTest.o: In function `global constructors keyed to 0_CuStrAlloc':
/home/p7539c/cutest/CuTest.c:379: undefined reference to `__gcov_init'
CuTest.o:(.data+0x184): undefined reference to `__gcov_merge_add'
collect2: ld returned 1 exit status
make: *** [TestTest] Error 1

我似乎找不到缺失符号的位置。在运行gcc版本4.1.2的机器上,gcov存在。

有什么想法吗?谢谢。

编辑后:

使用只包含一个.c文件的应用程序时,gcov似乎一切正常。当我有多个.c文件(因此有多个.o文件)时,我遇到了上述问题。

编译步骤如下:

cc -fprofile-arcs -ftest-coverage -g   -c -o AllTests.o AllTests.c
cc -fprofile-arcs -ftest-coverage -g   -c -o CuTestTest.o CuTestTest.c
cc -fprofile-arcs -ftest-coverage -g   -c -o CuTest.o CuTest.c
8个回答

84

我刚刚花费了大量时间调试一个非常类似的错误。这是我的经验教训:

  • 编译时必须传递-fprofile-arcs -ftest-coverage
  • 链接时必须传递-fprofile-arcs
  • 当链接时依然可能出现奇怪的链接器错误。它们看起来像这样:

    libname.a(objfile.o):(.ctors+0x0): undefined reference to 'global constructors keyed to long_name_of_file_and_function'

这意味着gconv在处理编译器生成的构造函数(在我的情况下,是复制构造函数)时出现了问题。检查错误消息中提到的函数,查看它复制构造哪些对象,并查看其中是否有任何类没有复制构造函数。添加一个,错误就会消失。

编辑:是否进行优化也会影响此问题。如果遇到问题,请尝试打开/关闭优化。


2
这个工作得非常好。感谢您花费了大量时间进行调试。 - Wyatt
2
使用“CFLAGS =”-O0 -fprofile-arcs -ftest-coverage“LDFLAGS =”-fprofile-arcs“./configure <等等>”配置软件对我来说似乎很有效。谢谢。 - oherrala
@John146,@SlicedLime:两年过去了,这个答案居然还没有被采纳,真是太遗憾了。不过这个回答刚刚帮我省了好多时间。 - johnsyweb
4
似乎没有必要在LDFLAGS中指定"-fprofile-arcs"选项,因为这些操作是在创建目标文件时完成的。你唯一需要做的就是在程序中链接libgcov。 - Calmarius

16

你需要的标志是链接时的-lgcov。也就是说,将:

gcc AllTests.o CuTestTest.o CuTest.o -o TestTest
gcc -lgcov AllTests.o CuTestTest.o CuTest.o -o TestTest

4
可以使用 --coverage 作为链接器标志,代替 -lgcov - MKroehnert

14

我在这里建议的方式中发现,当使用-fprofile-arcs -ftest-coverage编译包含.o文件的共享库时,将-lgcov添加到构建行中可以解决此问题。当然,也需要将可执行文件链接到-lgcov。构建共享库的命令如下:

g++    -shared -o libMyLib.so src_a.o src_b.o src_c.o -lgcov

然后执行文件,如下所示:

g++ -o myExec myMain.o -lMyLib -lgcov

将 -lgov 添加到共享库的构建中(不仅仅是 exe),使我解决了这个额外的错误:

hidden symbol `__gcov_merge_add' in /usr/lib/gcc/x86_64-redhat-linux/4.1.2/libgcov.a(_gcov_merge_add.o) is referenced by DSO
/usr/bin/ld: final link failed: Nonrepresentable section on output

请注意,-lgcov 必须是最后一个链接的库。


太棒了。我试图在开发人员使用CMake时添加新信息,但建议的编辑被拒绝了...谢谢,伙计们。 - Tarod
2
我更喜欢在答案中写下下一个解释。无论如何,使用CMake,您可以在“target_link_libraries (${LIBRARY_NAME} gcov)”之后添加“target_link_libraries (${LIBRARY_NAME} gcov)”以获得相同的行为。 - Tarod
这应该可以工作。我还没有尝试过,尝试后我会更新我的反馈。 - sandun dhammika
“输出中的不可表示部分”错误可能会发生在您端上编译的某些内容声明了标记为隐藏的内容,但内部依赖未得到满足的情况下。例如:extern __attribute__((visibility ("hidden"))) void some_function();,其中 some_function() 在链接时没有通过对象或静态库提供。 - Brian Vandenberg

14

编译和链接时,只需要在命令行上指定 --coverage 参数即可。

根据man gcc的说明:

该选项是 -fprofile-arcs-ftest-coverage(编译时)以及 -lgcov(链接时)的同义词。


6

我尝试了一个简单的测试文件,使用 gcc -ftest-coverage -fprofile-arcs test.c 命令,并没有出现你所描述的问题。

我怀疑如果在链接时加入 -ftest-coverage 标志,那么gcc会引入gcov库。请尝试在gcc命令行中传递该标志。


尝试在单文件应用程序中使用它,它可以正常工作。但是我的多文件应用程序出现了问题。它可以编译成功,但好像在链接时出现了混乱。 - john146
p7539c@localhost cutest> make cc -fprofile-arcs -ftest-coverage -g -c -o AllTests.o AllTests.c cc -fprofile-arcs -ftest-coverage -g -c -o CuTestTest.o CuTestTest.c cc -fprofile-arcs -ftest-coverage -g -c -o CuTest.o CuTest.c gcc AllTests.o CuTestTest.o CuTest.o -o TestTest - john146
2
你在最后一次调用gcc时仍未传递-ftest-coverage参数。链接时也需要指定它。 - flodin
2
就像slicedlime所说的那样,链接时需要的不是-ftest-coverage,而是-fprofile-arcs。 - Zitrax

3

很显然,当使用非gcc链接器进行链接时,会产生此错误消息。我们在使用ifort(因为我们的代码包括Fortran和C模块)进行链接时遇到了这个错误。切换到使用gcc进行链接就解决了问题。


由于其他链接器不识别“-fprofile-arcs”选项。 - Mawg says reinstate Monica

2

尊敬的Max Lybbert先生,

基本上,在使用autoconf时,需要添加_LDADD = -lgcov ...

这将解决问题。


-1

所以我在CFLAGS中添加了-shared,现在似乎可以处理多个文件了。当然,它在一个奇怪的地方崩溃了,所以我还不知道是怎么回事。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接