gcov不会生成头文件的覆盖率信息
我第一次使用gcov,并且遇到类似于此线程中报告的问题。 但是,在该主题中的评论之后,我无法解决我的问题。
我正在测试KMyMoney-4.6.4中具体测试用例的覆盖率,即测试文件“mymoneyaccounttest.cpp”中的“testConstructor”。 该测试用例使用以下方法,该方法位于头文件“mymoneyaccount.h”中,并具有可执行代码:
const QString& institutionId(void) const {
return m_institution;
}
因此,我构建了程序和测试,然后执行:gcov mymoneyaccount.cpp
在显示的覆盖范围信息中,我获得:
...文件'mymoneyaccount.cpp'执行的行数:393的8.91%创建'mymoneyaccount.cpp.gcov'
文件'mymoneyaccount.h'执行的行:创建'mymoneyaccount.h.gcov'的25.00%...
“mymoneyaccount.cpp.gcov”中的覆盖范围信息是可以的。 相反,“mymoneyaccount.h.gcov”显示:
6: 81:class KMM_MYMONEY_EXPORT MyMoneyAccount : public MyMoneyObject, public MyMoneyKeyValueContainer
...
-: 192: const QString& institutionId(void) const {
-: 193: return m_institution;
-: 194: }
...
-: 272: int accountCount(void) const {
#####: 273: return m_accountList.count();
-: 274: };
也许我错了,但这个结果意味着gcov不考虑“返回m_institution” 作为可执行代码,同时考虑将“返回m_accountList.count()”作为可执行代码。 此外,它在类声明的行中显示“6”,因此该文件具有覆盖信息,但不是我所期望的。
我不得不说,也许这个问题与文件和目录的名称有关:
1-目标文件在以“.cpp.o”结尾的“CMakefiles / kmm_mymoney.dir”中创建,例如mymoneyaccount.cpp.o。 因此,使用名称“mymoneyaccount.cpp.gcno”和“mymoneyaccount.cpp.gcda”(当然,在“CMakefiles / kmm_mymoney.dir”目录中)创建“gcno”和“gcda”文件。
2-当我执行时:gcov -o CMakeFiles / kmm_mymoney.dir mymoneyaccount.cpp gcov给出以下错误:
mymoneyaccount.gcno:无法打开笔记文件
所以我必须重新命名这些文件:mv mymoneyaccount.cpp.gcno mymoneyaccount.gcno mv mymoneyaccount.cpp.gcda mymoneyaccount.gcda
最后,我还有一个问题。 当我在包含测试用例的文件中执行gcov时,我的意思是,“gcov mymoneyaccounttest.cpp”而不是“gcov mymoneyaccount.cpp”,我也获得了“mymoneyaccount.h.gcov”文件,但覆盖率信息更差:
#####: 81:class KMM_MYMONEY_EXPORT MyMoneyAccount : public MyMoneyObject, public MyMoneyKeyValueContainer
无论如何,问题是:我应该在实现文件“mymoneyaccount.cpp”还是在测试文件“mymoneyaccounttest.cpp”中执行“gcov”?
抱歉的长度。 谢谢。
非常感谢Tony! 该链接有解决方案。 我只是将优化从-O2更改为-O0,现在结果是:
1: 192: const QString& institutionId(void) const {
1: 193: return m_institution;
-: 194: }
我必须注意,要获得“mymoneyaccount.cpp.gcov”,我执行“gcov mymoneyaccount.cpp”,但要获得“mymoneyaccount.h.gcov”,我必须执行“gcov mymoneyaccounttest.cpp”。 你知道为什么吗? 这两个文件都包含“mymoneyaccount.h”。
有覆盖范围信息,但不是我所期望的。
这可能是一个XY问题,因为你认为你的程序以你相信的方式执行,但它完全不同。
我会告诉你一个非常简单的程序:
class Example
{
private:
int value;
public:
Example(const Example& in): value(in.value)
{
std::cout << "Here we copy" << std::endl;
}
Example(int _value): value(_value)
{
std::cout << "Runs with default" << std::endl;
}
Example( Example&& in): value( in.value)
{
std::cout << "Moved away" << std::endl;
}
void show()
{
std::cout << "value " << value << std::endl;
}
};
Example GetIt()
{
return Example(2);
}
int main()
{
Example ex(Example(1));
ex.show();
std::cout << "----------------" << std::endl;
Example ex2( GetIt());
ex2.show();
}
输出是:
Runs with default
value 1
Runs with default
value 2
正如你所看到的,没有你期望的拷贝构造函数被调用,并且也没有调用构造函数。 建设简直没有了! 那么你期望gcov打印出什么? 它只是用int参数打印调用直接调用构造函数。 没有其他的!
你说:
我需要获得完整的覆盖信息...
根本没有办法获得更多的信息作为事实!
如果您的期望与您从分析工具中获得的结果完全不同,请检查您的假设是否正确。 对于我的期望,gcov和gprof工具非常好,代码的工具几乎完美。 但是将被优化掉的代码将不会生成任何调试/分析/覆盖信息。 调试并不总是如此,因为新版本的gcc会生成一些元信息,这些元信息可以链接到原始源代码,如果代码不再存在于可执行文件中,也可以设置断点。 但对于遗漏的构造函数,在调试时没有任何东西存在,因为程序流程只是简单地改变了! 没有cout
,没有调用构造函数,也没有进一步的分析/覆盖信息。 该代码根本不被执行,并且根本没有被使用。 正如你所看到的, cout
不叫! 这只是告诉你,代码被“修改”,以其他方式进行操作,就像你已经编码了一样!
我的例子只显示了优化的一个方面! 这只是消除! 还有很多其他优化步骤和策略,还有O0
! 注意我的代码是用O0
编译的,拷贝结构被移走了!
提示:
如果您的调试/覆盖/分析看起来与您的期望不同:请查看程序集以找出真正执行的内容以及涉及哪些源代码行。 你可以调用objdump来获得混合的源代码和汇编器!
如果你缩减你的优化器,请记住你的程序只是运行不同的代码。 没有一个“智能”的解释,结果是不可能的。 这需要一些如何处理这些数据的经验。
如果您确实需要“完整”信息,请问为什么!
如果您认为程序执行路径上没有足够的信息,您应该很高兴! 通常这正好告诉你,通过优化你的执行会缩短一点。
如果你没有在单行/方法中获取分析信息:只需查看使用/调用此功能的块即可。 大部分时间消耗很短,以至于进一步的调查毫无用处。
我想完成我给@Klaus的答案。
“-O2 -g”和“-O2”这两种组合都给出了该方法的以下覆盖范围信息(我插入的信息仅用于确保方法在测试中执行):
-: 192: const QString& institutionId(void) const {
1: 193: std::cout << "Inside institutionIdn";
-: 194: return m_institution;
-: 195: }
这意味着行192和194不被视为可执行文件,但仅限于cout。 标志-g不影响结果(至少在这种情况下)。
如果我使用“-O0”构建程序,结果是:
1: 192: const QString& institutionId(void) const {
1: 193: std::cout << "Inside institutionIdn";
1: 194: return m_institution;
-: 195: }
链接地址: http://www.djcxy.com/p/51011.html
上一篇: gcov is not generating coverage information for header files