假设我在verify()
内有一个名为verify.c
的函数,它用于评估条件并在检查失败时打印调试消息。
void verify(int expected)
{
if (expected < 10) {
fprintf(stderr,"Verification failed for %d\n", expected);
abort();
}
}
现在,我将在整个SW软件包的各个c文件中添加此头文件verify.h
,并且来自不同c文件的许多函数都在调用verify()
。如果检查失败,verify()
将打印出错误消息,但是我如何确切地找出错误的根源(即哪个文件和哪个函数实际上调用失败verify()
)?
我想在编译代码时找到它,而不使用gdb
之类的调试器。
答案 0 :(得分:3)
如果使用的是gcc,则应该能够使用__FILE__
, __LINE__
, and __FUNCTION__
预处理程序宏,并将它们传递给verify()
例程以发出更有用的调试消息。正如塔德曼(tadman)在其评论中指出的那样,定义一个宏作为verify()
的包装器,在将文件,行和函数信息传递给verify()
之前,可能会有意义。然后,在使用时,您只需要调用包装器并传递expected
参数,让预处理器在上下文中仍可用的情况下填充额外的信息,然后将其全部传递给{{1 }}功能。
答案 1 :(得分:3)
给出verify.h声明:
#define verify(e) verify_impl( (e), __FILE__, __func__, __LINE__ )
void verify_impl( int expected, const char* file, const char* fn, int line ) ;
然后对verify.c进行定义:
void verify_impl(int expected, const char* file, const char* fn, int line ) ; )
{
if (expected < 10)
{
fprintf( stderr,"Verification failed for %d at %s:%s(%d)\n",
expected, file, fn, line );
abort();
}
}
例如,在bar.c的第20行从verify(9) ;
调用foo()
时,您将得到:
Verification failed for 9 at bar.c:foo(20)
但是,更通用的断言机制是可能的。考虑:
verify.h:
#define verify(e) verify_impl( (e), #e, __FILE__, __func__, __LINE__ )
void verify_impl( int exp, const char* expression,
const char* file, const char* fn, int line ) ;
verify.c
void verify_impl( int exp, const char* expression,
const char* file, const char* fn, int line ) ; )
{
if( !exp )
{
fprintf( stderr,"Verification that %s failed at from %s:%s(%d)\n",
expression, file, fn, line );
abort();
}
}
例如,当在bar.c的第20行从verify( x >= 10 ) ;
用x == 9
调用foo()
时,您会得到更多的帮助:
Verification that x >= 10 failed at bar.c:foo(20)
可以验证任何布尔表达式,而不是硬编码的exp < 10
。如果仍然需要原始的硬测试,则可以根据新的更灵活的宏定义另一个宏:
#define verify_notlessthan10( e ) verify( (e) >= 10 )
请注意逻辑的反转;您正在验证表达式为 true ,并且在 false 时中止。语义是 assert 的语义。
答案 2 :(得分:0)
一种解决方案是像这样修改代码:
void verify(int expected, char * str)
{
if (expected < 10) {
fprintf(stderr,"Verification failed for %d\n", expected);
if(str)
fprintf(stderr, str);
abort();
}
}
使用这种方法,您将需要修改所有呼叫。一种解决方法是将函数重命名为verify_aux
或类似的名称,然后编写以下代码:
void verify(int expected)
{
verify_aux(expected, NULL);
}
这样,如果您需要在特定时间点将验证更改为verify_aux。