evr*_*rn0 8 c debugging trace design-patterns
我正在为用C编写的自动化系统开发一些模块,我需要使用硬件执行大量工作.我没有看到调试事物而不是跟踪日志的简单方法(如传统方法).所以我正在寻找一个记录函数调用的好习惯.至少调用和返回值的顺序.
它在应用程序中执行的方式非常简单,并且实际上使用不相关的构造来污染代码
int function (int param){
if(trace_level & LOG_FCALLS){
writelog("Entering function()");
}
/* something useful */
if(trace_level & LOG_FCALLS){
writelog("Exit from function()=%d", ret);
}
}
Run Code Online (Sandbox Code Playgroud)
我决定使用一个可以完成所有脏工作的宏.现在看起来像这样
#define LOG_E(fn) const char *__fname=fn; printf("LOG: Entry to %s\n",__fname)
#define return(ret) printf("LOG: Exit from %s()=%d\n",__fname,ret)
int testFunc(){
LOG_E("testFunc");
/*do useful things */
return(ret);
}
Run Code Online (Sandbox Code Playgroud)
我看到了这段代码的问题
我正在覆盖return语句,它需要一直写return(ret)而不是return ret.很容易忘记这个问题.
我在我的宏中定义字符串变量.我知道__func__宏存在于C99中,但不幸的是,我的编译器不支持这个宏或任何其他相关的宏.
如何记录函数参数的值?
我很确定这不是一个新问题,我不是第一个面对它的人.我也知道AOP的事情,但代码检测是我的系统不可接受的解决方案,我没有发现任何可能与我的编译器.
所以我正在寻找一个好主意如何以最优雅的方式实现跟踪.
我的环境:传统代码,C,Watcom 10.x,实时操作系统
执行此操作的超级严谨,专业的方法是创建一个单独的调试/测试项目,该项目完全独立于生产代码.它是这样的:
创建一个.txt日志文件,您可以在其中编写要记录的每个函数的完整签名,例如:
int function (int param)
float function2 (void)
...
Run Code Online (Sandbox Code Playgroud){之前和之后,它将调试日志代码插入所需的函数中}.你需要几个小时的时间来完成这样的计划.上面的方法是我自己在关键任务软件上做的,你有安全标准(MISRA,代码覆盖等)的要求,说没有允许在最终产品中执行的代码.
此方法可确保生产代码的完整性,并确保测试/调试代码不会将任何意外错误添加到程序中.它还使生成代码中的编译开关等杂乱无章.并且您将不会在您的项目中保留任何旧的调试代码而您忘记删除(否则我总是在我的程序中忘记一些调试代码片段).
#if defined(DEBUG_BUILD)
# define START_FUNCTION if(trace_level & LOG_FCALLS){writelog("+++ %s()", __func__)
}
# define END_FUNCTION if(trace_level & LOG_FCALLS){writelog("--- %s()", __func__)
#elif defined (TIMING_BUILD)
# define START_FUNCTION WRITE_TIMED_LOG("+++")
# define END_FUNCTION WRITE_TIMED_LOG("---")
#else
# define START_FUNCTION
# define END_FUNCTION
#endif
int function (int param){
START_FUNCTION;
...
if(error_occurred) {
END_FUNCTION;
return errror_code;
}
...
END_FUNCTION;
return 42;
}
Run Code Online (Sandbox Code Playgroud)