gcov没有为头文件生成覆盖率信息

时间:2015-09-01 11:15:59

标签: c++ qt gcc gcov

我第一次使用gcov而我遇到的问题类似于此thread中报告的问题。但是,在该主题中的评论之后,我无法解决我的问题。

我正在尝试测量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' 执行的行数:4的25.00% 创建'mymoneyaccount.h.gcov' ...

“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-目标文件在“CMakefiles / kmm_mymoney.dir”中创建,以“.cpp.o”结尾,例如mymoneyaccount.cpp.o。因此,“gcno”和“gcda”文件的名称为“mymoneyaccount.cpp.gcno”和“mymoneyaccount.cpp.gcda”(当然,在“CMakefiles / kmm_mymoney.dir”目录中)。

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”吗?

抱歉这个长度。感谢。

3 个答案:

答案 0 :(得分:1)

非常感谢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"。

答案 1 :(得分:1)

  

有覆盖率信息但不是我期望的。

这可能是一个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未被调用!这只是告诉你代码是&#34;修改&#34;以你编码的其他方式操作!

我的例子只显示了优化的一个方面!这只是为了取消!还有许多其他优化步骤和策略,O0!请注意我的代码是使用O0编译的,并且复制结构已移开!

提示:

  • 如果您的调试/覆盖/分析看起来与您的期望不同:查看程序集以找出实际执行的内容以及涉及的源代码行。您可以调用objdump来为此获取源和汇编程序混合!

  • 如果缩小优化程序,请记住程序只运行不同的代码。没有&#34;智能&#34;解释。这需要一些如何处理这些数据的经验。

  • 如果你真的需要&#34;完整&#34;信息,问为什么!

  • 如果您认为在程序执行路径上没有足够的信息,那么您应该感到高兴!通常这正好告诉你,通过优化你的执行会稍微缩短。

  • 如果您没有获得关于单行/方法的分析信息:只需查看使用/调用此功能的块。大部分时间消耗都很短,以至于进一步的调查毫无用处。

答案 2 :(得分:0)

我想完成我给@Klaus的答案。

两种组合&#34; -O2 -g&#34;和&#34; -O2&#34;给出了此方法的以下覆盖信息(我只插入了消息以确保在测试中正在执行该方法):

-:  192:  const QString& institutionId(void) const {
1:  193:    std::cout << "Inside institutionId\n";
-:  194:    return m_institution;
-:  195:  }

这意味着第192和194行不被视为可执行文件,而只是cout。标志-g不会影响结果(至少在这种情况下)。

如果我使用&#34; -O0&#34;构建程序,结果是:

1:  192:  const QString& institutionId(void) const {
1:  193:    std::cout << "Inside institutionId\n";
1:  194:    return m_institution;
-:  195:  }