如何检测程序是否在valgrind中运行?

时间:2008-12-13 17:18:30

标签: c++ unit-testing valgrind

有没有办法在运行时识别可执行文件是从valgrind中运行的?我有一组C ++单元测试,其中一个期望std::vector::reserve抛出std::bad_alloc。当我在valgrind下运行时,它完全挽救,阻止我测试内存泄漏(使用valgrind)和行为(期望抛出异常)。

这是一个重现它的最小例子:

#include <vector>
int main()
{
    size_t uint_max = static_cast<size_t>(-1);
    std::vector<char> v;
    v.reserve(uint_max);
}

运行valgrind,我得到了这个输出:

Warning: silly arg (-1) to __builtin_new()
new/new[] failed and should throw an exception, but Valgrind
   cannot throw exceptions and so is aborting instead.  Sorry.
   at 0x40192BC: VALGRIND_PRINTF_BACKTRACE (valgrind.h:319)
   by 0x401C823: operator new(unsigned) (vg_replace_malloc.c:164)
   by 0x80487BF: std::vector<char, std::allocator<char> >::reserve(unsigned) new_allocator.h:92)
   by 0x804874D: main (vg.cxx:6)

我想修改单元测试,以便在从valgrind中运行时简单地跳过有问题的代码。这可能吗?

3 个答案:

答案 0 :(得分:18)

您应该从Valgrind手册中查看this page,它包含一个RUNNING_ON_VALGRIND宏(包含在valgrind.h中),可以满足您的需求。

答案 1 :(得分:3)

如果不想包含valgrind.h(需要进行autoconf测试或类似的测试)或不使用包装器,那么这对于Linux(以及其他使用ELF的系统?)是一种启发式方法:测试{{ 1}}环境变量,因为Valgrind通过预加载库来工作。我在C语言中使用以下测试来检查LD_PRELOAD是否包含字符串LD_PRELOAD"/valgrind/"

"/vgpreload"

其他系统可能具有类似的解决方案。我建议使用以下命令来查看环境是否提到了Valgrind:

int tests_run_within_valgrind (void)
{
  char *p = getenv ("LD_PRELOAD");
  if (p == NULL)
    return 0;
  return (strstr (p, "/valgrind/") != NULL ||
          strstr (p, "/vgpreload") != NULL);
}

答案 2 :(得分:0)

我查看了valgrind doucmentation并没有找到一个简单的答案。但是您可以尝试以下几种方法:

  • 围绕有问题的新操作编写自己的包装器,并在valgrind获取其私有新函数之前引发异常。

  • 尝试上面提到的海报,除了使用环境变量代替命令行选项(需要管道):

    MYAPP_UNIT_TESTS_DISABLED="NEW_MINUS_ONE,FLY_TO_MOON,DEREF_NULL" valgrind myapp
    

然后你可以轻松编写一个函数

bool unit_test_enabled(const char *testname);

根据getenv(3)返回的值保护您的单元测试。