我第一次使用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”吗?
抱歉这个长度。感谢。
答案 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: }