1. 目标

设计一个函数库,封装五个函数,实现日志输出与断言判断等功能

  1. 函数原型及其实现

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;

}

  1. 测试

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 通用函数库之调试功能封装相关推荐

  1. Boost库-功能介绍-Geometry-图形开发库-计算几何-常用功能封装-GraphicalDebugging(二)

      有了上一篇博文打下的基础,读者应该对分析查看几何图形有了初步了解,本着实用的原则,这篇文章,主要介绍Geometry的常用计算.它提供了点线面相交,相离的判断,以及多边形的布尔运算,在几何分析中非 ...

  2. Golang 中通过 cgo 调用 C++ 的动态库的功能封装

    将C++warpper 文件写在go中: https://github.com/winlinvip/go-fdkaac/blob/master/fdkaac/dec.go https://github ...

  3. VC使用CRT调试功能来检测内存泄漏

    信息来源:csdn      C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:"最大的长处也可能成为最大的弱点",那么 C/C++ 应用程序正好印证 ...

  4. VC++ 6.0 中如何使用 CRT 调试功能来检测内存泄漏[转]

    /C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:"最大的长处也可能成为最大的弱点",那么 C/C++ 应用程序正好印证了这句话.在 C/C++ 应用程 ...

  5. 使用CRT调试功能来检测内存泄漏

    C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:"最大的长处也可能成为最大的弱点",那么 C/C++ 应用程序正好印证了这句话.在 C/C++ 应用 ...

  6. vue使用xe-utils通用函数库

    目录 一.xe-Utils介绍 二.xe-utils API介绍 API全局参数 基础函数 常用函数 日期函数 高级函数 浏览器函数 三.如何全局使用xe-utils 3.1 安装xe-utils 3 ...

  7. vue组件封装技巧,如何对vue模块进行功能封装

    如何对vue模块进行功能封装,vue组件封装技巧 当业务不断累加,导致原本干净整洁的代码越来越冗余,各种变量和注释已经让他人望而却步,往往又苦于重构带来的成本,导致诞生很多巨石应用.与其让自己或他人面 ...

  8. [转载]eclipse的远程调试功能配置

    原文地址:eclipse的远程调试功能配置作者:我的 用途:web应用部署并运行于外部(区别于eclipse环境中启动的)应用服务器中,当出现问题时,可以使用eclipse工程的源代码进行跟踪调试. ...

  9. idea调试怎么跳出循环_使用IDEA的Debug调试功能,查看程序的运行过程

    Debug追踪,使用IDEA的断点调试功能,查看程序的运行过程 知乎视频​www.zhihu.com 1. 在有效代码行,点击行号右边的空白区域,设置断点,程序执行到断点将停止,我们可以手动来运行程序 ...

最新文章

  1. Java入门学习注意事项有哪些?
  2. probable oracle net,ORA-28547: connection to server failed, probable Oracle Net admin error
  3. Type mismatch:
  4. this指针不全等于对象地址
  5. 降低软件复杂性一般原则和方法
  6. 【转】JAVA 调用Web Service的方法
  7. MySQL中GTID的几个限制和解决方案(r13笔记第21天)
  8. 【翻译】Geometric Features-Based Parking Slot Detection
  9. 数据库大数据量的优化方案
  10. ADF单位根检验三种形式_【EViews】面板数据的处理方法及检验步骤
  11. 分数化简java_中国MOOC分数——Java
  12. linux sticky权限,Linux基础入门篇之文件高级权限suid,sgid,sticky
  13. 输入一个整数,若为奇数则输出其平方根,否则输出其立方根(分别用单分支、双分支和条件运算实现)
  14. Xshell下载安装(解决评估过期问题)
  15. 服务器运维1-failed to start LSB
  16. 企业微信寄件审批教程
  17. 字符串分割(split),将字符串按照指定字符进行分割。split(String regex)和split(String regex, int limit)
  18. 四、RNN模型 与 NLP应用 —— Stacked RNN
  19. 我所首席执行主任律师王杰接受《电脑报》记者采访就sp发展发表观点
  20. 洛谷4168 [Violet]蒲公英

热门文章

  1. javascript中变量没有块级作用域---函数内申明的变量在整个函数中都有效!
  2. python_restframework(频率组件)
  3. java笔记 -- GregorianCalendar和DateFormateSymbols 类方法
  4. 从源码看runLoop
  5. LFS、BLFS、ALFS、HLFS的区别
  6. ActivityMQ消息持久化到HANA数据库
  7. 各版本jdk下载地址
  8. 大学生应该学习python和linux而不是matlab和windows
  9. iphone6 iphone6 plus 放大显示模式高分辨率模式问题
  10. JavaScript 小记 之 闭包(Closures)