gcov 和全局析构函数

Posted

技术标签:

【中文标题】gcov 和全局析构函数【英文标题】:gcov and global destructors 【发布时间】:2011-09-16 09:03:26 【问题描述】:

MWE

#include <iostream>

struct Foo 
  Foo() 
    std::cout << "Constructing Foo " << this << std::endl;
  

  ~Foo() 
    std::cout << "Destructing Foo " << this << std::endl;
  
;

Foo global_foo;

int main () 
  std::cout << "Entering and exiting main()" << std::endl;
  return 0;

问题

用选项-fprofile-arcs -ftest-coverage编译上面的代码,运行程序,然后运行gcov。程序输出清楚地显示 Foo::Foo()、main() 和 Foo::~Foo() 是按此顺序调用的。 gcov 输出显示调用了 Foo::Foo() 和 main(),但没有调用 Foo::~Foo()。

根本原因

全局对象被 GNU 内部退出处理程序(使用 at_exit() 注册的函数)销毁。最终的 gcov 统计数据由另一个退出处理程序生成。 gcov 退出处理程序显然是在全局销毁退出处理程序之前调用的,因此 gcov 看不到被调用的析构函数。

错误状态

这是 gcov 中的一个旧的 错误。这是 Bugzilla 链接:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=7970。九年后,该错误仍然存​​在,至少在 i686-apple-darwin10-g++-4.2.1 中。

问题

这是 gcov 中一个无法解决的错误,是我必须忍受的问题,还是只是碰巧从裂缝中溜走的东西(九岁,完全被遗忘了)?如果是后者,如何解决?

【问题讨论】:

一些赞成票,一个反对票(没有评论?),但到目前为止没有答案或 cmets。是否有任何堆栈溢出成员有办法与 gcc 开发团队沟通? 【参考方案1】:

首先,请注意,自 2005 年以来,该错误报告尚未得到重新确认;您可能应该添加一条说明,说明您仍然看到 g++-4.2.1 中的不良行为。即使没有人对您的消息采取行动,将这些信息公开也很有用。

短期内,如果你想继续使用 gcov,你必须忍受它。您可能会考虑使用lcov,它使您能够从覆盖分析中排除指定的行。公平警告:我听说它很好,但我自己从未使用过。

中期,将该响应添加到错误跟踪器!没有保证,但也许这会产生足够的兴趣让某个好心人给你写一个补丁。

长期来看,如果没有人愿意为你打补丁,你也许可以自己打补丁。 gcc 不是世界上最友好的代码库,让您的更改被接受可能是一种冒险,但如果您真的需要它,您可以实现它。

祝你好运。

【讨论】:

感谢您的回复。我添加到 bugzilla 报告中。短期的答案显然是“忍受它”。我们的产品是一个 C++ 库,其主要用途是在自动编码的仿真环境中。由于这是我们的预期目标,因此我们的许多测试都是在该环境中完成的。该环境的最新版本创建了全局静态数据。我们还具有绕过该环境的单元测试功能。所以一个明显的解决方案是要求开发人员开发 ctor_dtor 单元测试。 (我已经做到了,而且我已经听到了抱怨。)

以上是关于gcov 和全局析构函数的主要内容,如果未能解决你的问题,请参考以下文章

MFC 断言在全局析构函数中工作

如何强制调用类的全局实例的析构函数和构造函数(因此“重新初始化”类实例)

c++ 析构函数 是在啥时候执行

简述构造函数和析构函数的作用

C++ 构造函数 & 析构函数

对象的构造与析构