专题 4 通用函数库之调试功能封装
- 目标
设计一个函数库,封装五个函数,实现日志输出与断言判断等功能
- 函数原型及其实现
2.1 格式化日志输出函数:PrintLog PrintTraceLog
原型:int PrintLog(FILE *pfile, const char *pformat, …);
功能说明:按照字符串pformat的内容,控制后继参数的数量和格式,并在文件流中输出。
原型:int PrintTraceLog(char *pformat, …);
功能说明:调用PrintLog将信息写入日志文件
2.2 源码
int PrintLog(FILE *pfile, const char *pformat, ...)
{
va_list _va_list;//声明变长参数列表
TIMESTRU timestru;
char szBuf[1024];
int nLen;
if(pformat == NULL || pfile == NULL)/*参数合法性检查*/
return -1;
timestru = GetTime();//定义在后面专题
nLen = sprintf(szBuf, "INFO: %04d.%02d.%02d.%02d:%02d:%02d [%d]: ",
timestru.nYear, timestru.nMon, timestru.nDay,
timestru.nHour, timestru.nMin, timestru.nSec, getpid());
va_start(_va_list, pformat);//初始化变长参数列表
nLen += vsprintf(szBuf + nLen, pformat, _va_list);//传递变长参数列表
va_end(_va_list);//结束使用变长参数列表
nLen += sprintf(szBuf + nLen, "/n");//添加换行符
if(fputs(szBuf, pfile) != EOF && fflush(pfile) != EOF)//输出并刷新文件流
return 0;
return -2;
}
int PrintTraceLog(const char *pformat, ...)
{
FILE *fp = NULL;
int ret = -1;
if((fp = fopen(TRACE_FILE, "a")) != NULL)
{
ret = PrintLog(fp, pformat);//写日志文件
fclose(fp);
return ret;
}
return ret;
}
2.3 内存打印函数
原型:int PrintHexLog(FILE *pfile, void *pData, int nSize)
功能:将一段内存内容写入输出流
原型:int PrintTraceHexLog(void *pData, int nSize)
功能: 调用PrintHexLog将一段内存内容写入日志文件中
2.4 源码
/**
**打印一段内存
*/
int PrintHexLog(FILE *pfile, void *pData, int nSize)
{
char szBuf[1024];
char cLine[1024];
int nLen=0;
int nPos;
int nLineSize;/*每行的字节数,小于或等于16*/
int n;
int nLine; /*行号*/
PrintLog(pfile, "address[%d] size[%d]", cLine, nSize);
for(nPos = 0; nPos < nSize; nLine++)
{
nLineSize = min(nSize - nPos, 16);
memcpy(cLine, (char*)pData + nPos, nLineSize);
nPos += nLineSize;
nLen += sprintf(szBuf + nLen, "[%02d]: ", nLine);
for(n = 0; n < nLineSize; n++)
{
if(n == 8)
{
nLen += sprintf(szBuf + nLen, " ");
}
nLen += sprintf(szBuf + nLen, "%02x ", cLine[n] & 0x00FF);
}
for(n = nLineSize; n < 16; n++)
{
if(n == 8)
nLen += sprintf(szBuf + nLen, " ");
nLen += sprintf(szBuf + nLen, " ");/*三个空格*/
}
nLen += sprintf(szBuf + nLen, " :");
for(n = 0; n < nLineSize; n++)
{
if(!isprint(cLine[n]))
cLine[n] = '.';
nLen += sprintf(szBuf + nLen, "%c", cLine[n]);
}
nLen += sprintf(szBuf + nLen, "/n");
}
if(fputs(szBuf, pfile) != EOF && fflush(pfile) != EOF)
return 0;
return -1;
}
int PrintTraceHexLog(void *pData, int nSize)
{
FILE *fp = NULL;
if((fp = fopen(TRACE_FILE, "a")) != NULL)
{
PrintHexLog(fp, pData, nSize);
fclose(fp);
}
return 0;
}
2.5 信息判断函数
原型:int Verify(int bStatus, const char *szBuf, const char *szFile, int nLine)
功能:当标志bStatus为真时,函数不执行任何操作,否则Verify将向日志文件输出错误信息。字符串szBuf描述了错误信息,字符串szFile描述了发生了错误的源文件名称,参数nLine代表发生错误所在的行号。
2.6 源码
int Verify(int bStatus, const char *szBuf, const char *szFile, int nLine)
{
FILE *fp;
char szFileLine[128], szError[128];
if(!bStatus)
{
memset(szFileLine, 0, sizeof(szFileLine));
memset(szError, 0, sizeof(szError));
if(errno != 0)
sprintf(szError, "/t> %0.64s/n", strerror(errno));
if(szFile == NULL)
strcpy(szFileLine, "/t> Invalid file name");
else
sprintf(szFileLine, "/t> In line %d file %0.32s", nLine, szFile);
if(szBuf == NULL)
szBuf = "";
fp = fopen(TRACE_FILE, "a");
if(fp != NULL)
{
PrintLog(fp, "%s[%d]/n%s%s", szBuf, getpid(), szError, szFileLine);
fclose(fp);
}
errno = 0;
}
return bStatus;
}
- 测试
3.1 源码
#include "comlib.h"
int main()
{
char buf[1024];
char buf2[1024];
int i = 1000;
PrintLog(stderr, "This is a test[%d]", i);
PrintTraceLog("This is test[%d]", i);
PrintHexLog(stderr, &i, sizeof(i));
PrintTraceHexLog(&i, sizeof(int));
PrintTraceLog("----------------------");
Verify(0, NULL, __FILE__, __LINE__);
PrintTraceLog("-----------------------");
VERIFY(0);
PrintTraceLog("-----------------------");
VERIFY(1);
return 0;
}
3.2 编译
gcc –Wall –O2 –o test test.c –I../include –L../lib -lcom
3.3 查看结果
控制台输出:
INFO: 2009.12.16.22:29:26 [3712]: This is a test[1000]
INFO: 2009.12.16.22:29:26 [3712]: address[2276496] size[4]
[00]: e8 03 00 00 :....
日志文件中的输出:
INFO: 2009.12.16.22:29:26 [3712]: This is test[2278552]
INFO: 2009.12.16.22:29:26 [3712]: address[2276464] size[4]
[4200138]: e8 03 00 00 :....
INFO: 2009.12.16.22:29:26 [3712]: ----------------------
INFO: 2009.12.16.22:29:26 [3712]: [3712]
> Illegal seek
> In line 13 file src/td1.c
INFO: 2009.12.16.22:29:26 [3712]: -----------------------
INFO: 2009.12.16.22:29:26 [3712]: [3712]
> In line 15 file src/td1.c
INFO: 2009.12.16.22:29:26 [3712]: -----------------------
转载于:https://my.oschina.net/fuyajun1983cn/blog/263809
专题 4 通用函数库之调试功能封装相关推荐
- Boost库-功能介绍-Geometry-图形开发库-计算几何-常用功能封装-GraphicalDebugging(二)
有了上一篇博文打下的基础,读者应该对分析查看几何图形有了初步了解,本着实用的原则,这篇文章,主要介绍Geometry的常用计算.它提供了点线面相交,相离的判断,以及多边形的布尔运算,在几何分析中非 ...
- Golang 中通过 cgo 调用 C++ 的动态库的功能封装
将C++warpper 文件写在go中: https://github.com/winlinvip/go-fdkaac/blob/master/fdkaac/dec.go https://github ...
- VC使用CRT调试功能来检测内存泄漏
信息来源:csdn C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:"最大的长处也可能成为最大的弱点",那么 C/C++ 应用程序正好印证 ...
- VC++ 6.0 中如何使用 CRT 调试功能来检测内存泄漏[转]
/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:"最大的长处也可能成为最大的弱点",那么 C/C++ 应用程序正好印证了这句话.在 C/C++ 应用程 ...
- 使用CRT调试功能来检测内存泄漏
C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:"最大的长处也可能成为最大的弱点",那么 C/C++ 应用程序正好印证了这句话.在 C/C++ 应用 ...
- vue使用xe-utils通用函数库
目录 一.xe-Utils介绍 二.xe-utils API介绍 API全局参数 基础函数 常用函数 日期函数 高级函数 浏览器函数 三.如何全局使用xe-utils 3.1 安装xe-utils 3 ...
- vue组件封装技巧,如何对vue模块进行功能封装
如何对vue模块进行功能封装,vue组件封装技巧 当业务不断累加,导致原本干净整洁的代码越来越冗余,各种变量和注释已经让他人望而却步,往往又苦于重构带来的成本,导致诞生很多巨石应用.与其让自己或他人面 ...
- [转载]eclipse的远程调试功能配置
原文地址:eclipse的远程调试功能配置作者:我的 用途:web应用部署并运行于外部(区别于eclipse环境中启动的)应用服务器中,当出现问题时,可以使用eclipse工程的源代码进行跟踪调试. ...
- idea调试怎么跳出循环_使用IDEA的Debug调试功能,查看程序的运行过程
Debug追踪,使用IDEA的断点调试功能,查看程序的运行过程 知乎视频www.zhihu.com 1. 在有效代码行,点击行号右边的空白区域,设置断点,程序执行到断点将停止,我们可以手动来运行程序 ...
最新文章
- Java入门学习注意事项有哪些?
- probable oracle net,ORA-28547: connection to server failed, probable Oracle Net admin error
- Type mismatch:
- this指针不全等于对象地址
- 降低软件复杂性一般原则和方法
- 【转】JAVA 调用Web Service的方法
- MySQL中GTID的几个限制和解决方案(r13笔记第21天)
- 【翻译】Geometric Features-Based Parking Slot Detection
- 数据库大数据量的优化方案
- ADF单位根检验三种形式_【EViews】面板数据的处理方法及检验步骤
- 分数化简java_中国MOOC分数——Java
- linux sticky权限,Linux基础入门篇之文件高级权限suid,sgid,sticky
- 输入一个整数,若为奇数则输出其平方根,否则输出其立方根(分别用单分支、双分支和条件运算实现)
- Xshell下载安装(解决评估过期问题)
- 服务器运维1-failed to start LSB
- 企业微信寄件审批教程
- 字符串分割(split),将字符串按照指定字符进行分割。split(String regex)和split(String regex, int limit)
- 四、RNN模型 与 NLP应用 —— Stacked RNN
- 我所首席执行主任律师王杰接受《电脑报》记者采访就sp发展发表观点
- 洛谷4168 [Violet]蒲公英
热门文章
- javascript中变量没有块级作用域---函数内申明的变量在整个函数中都有效!
- python_restframework(频率组件)
- java笔记 -- GregorianCalendar和DateFormateSymbols 类方法
- 从源码看runLoop
- LFS、BLFS、ALFS、HLFS的区别
- ActivityMQ消息持久化到HANA数据库
- 各版本jdk下载地址
- 大学生应该学习python和linux而不是matlab和windows
- iphone6 iphone6 plus 放大显示模式高分辨率模式问题
- JavaScript 小记 之 闭包(Closures)