如何触发错误的代码路径测试在C?



我经常为我的程序编写测试,以确保它们在任何情况下都能100%工作(这样以后我就不必花几个小时调试它们了)。

然而,到目前为止,我所有的测试都只是测试在正常情况下可以到达的代码行,因此,例如,我没有测试如果malloc()失败会发生什么。我也很想这样做,所以最近我开始尝试并寻找关于如何重写任何函数的答案,以便它返回任何预定义的值,并可能将errno设置为某些值。

我学习了dlsym, LD_PRELOAD和--wrap的链接器。到目前为止,我已经与dlsym取得了许多成功,甚至覆盖malloc(),它不会陷入无限循环,然而,我用来寻找内存泄漏的Valgrind似乎很高兴地忽略了我用dlsym包装的任何函数,因此,例如malloc()开始正常工作时,我不希望它在Valgrind下(因此返回NULL人为地不起作用)。

LD_PRELOAD通常与dlsym一起使用,它自己不做任何事情。

--wrap很好,但它的缺点是您需要知道要为每个文件覆盖的函数。这很烦人-使用dlsym,我可以在代码中选择函数,仅此而已,但是--wrap将使我的Makefile变得更加复杂。

我还尝试使用libc的隐藏定义(__libc_malloc(),__libc_function_name()一般)来覆盖malloc(),strxxx()和其他函数的弱符号,Valgrind喜欢覆盖,然后使用dlsym的其他一切,有点像这样:

void* __libc_malloc(size_t);
void* malloc(size_t size) {
if(malloc_fail) {
errno = ENOMEM;
return NULL;
}
return __libc_malloc(size);
}

但是,Valgrind也会很高兴地覆盖这个malloc实现,让我没有任何选择。

我也试过把我的内存泄漏检测器切换到libasan (gcc -fsanitize=address)之类的东西,但不幸的是,我对gcc附带的任何消毒器都有非常糟糕的经历,因为它们的错误实现,例如在使用pthread_cancel()时崩溃(像这里),结果我的代码需要测试一些pthread函数很好,因为我把它们包装在我自己的函数和结构和东西中。

是否有其他方法触发错误的代码路径?我做错了什么吗?

Valgrind为malloccallocfree提供了自己的包装器,这对其操作至关重要。我并不觉得这些替换了您试图为这些函数指定的任何包装器是令人惊讶的。主要的替代方案将是相反的:您的包装器取代valgrind的。

我建议简单地将您的测试分为那些依赖于您注入包装器的测试和那些不依赖于您注入包装器的测试。只对后一组的测试使用Valgrind。

这样做的方法是调用你的函数的malloc等以外的东西(如my_malloc)。

如果你这样做,你仍然希望Valgrind分析由my_malloc返回的内存,你将需要使用Valgrind客户端机制告诉Valgrind关于你的内存池,分配等。

请看这篇文章中的一个例子。

最新更新