给函数增加debug头(一)
来源:互联网 发布:中国建筑西北院 知乎 编辑:程序博客网 时间:2024/06/04 01:36
本文由 @lonelyrains 出品,转载请注明出处。
文章链接: http://blog.csdn.net/lonelyrains/article/details/7719614
调试程序时,经常需要查看程序的函数调用的流动方向。在PC上很简单,可以F10、F11单步调试查看或者gdb命令行查看。不过实际调试发现,在处理多重继承和虚函数的调用时,vc-express-2008的调试器单步并不能很好的发挥效用【目前还未单独针对这个结论做样例,以后再补上】。而在嵌入式设备上却很难实现单步调试。打印日志就成了很有用的调试方式。然而,在比较庞大的程序里,所有的函数头手动添加调试语句不太现实【自己一字一字码起来的除外,原因大家都懂的^_^】。所以想到了写个小工具,专门在所有的函数头添加调试语句。
废话少说,上代码:
#include <iostream> #include <vector> using namespace std; /*******************************************************功能:对输入的.h、.cpp文件的所有函数头增加打印条件:考察的代码文件能正常编译通过,本程序不进行文法、语义检查步骤: 1、读入文件[简化成申请合适空间一次性读入] 2、找到函数头[简化成不考虑有额外的宏定义的函数头] ①找到所有的不在单引号或者双引号之内的'{' ②排除'{'前导[非空和换行的字符]为if()、for()、while()、switch() ③排除'{'前导不是')' [不考虑 static / const 修饰函数] ③其余均为函数头 3、在'{'后添加打印:[回车换行]Debug_Func("tagxxx---func:%s,line:%d,file:%s",__FUNCTION__,__LINE__,__FILE__);[回车换行]*******************************************************/ #define SWITCH_LENGTH 6 #define FOR_LENGTH 3 #define WHILE_LENGTH 5 #define IF_LENGTH 2 #define BUF_SIZE 100000#define PATH_SIZE 300 #define DBG_LENGTH 20 const char *debugSentence = "\nDebug_Func(\"tagxxx---func:%s,line:%d,file:%s\\n\",__FUNCTION__,__LINE__,__FILE__);" ; vector<int> debugPlace;//记录每次有效{的位置 void readfile(const char *filename, char *buf) { FILE* fp = fopen(filename,"rb"); //改成rb之后正常了...奇怪,明明是txt文件,fread内容不对,多出一段。这个地方很典型。可能c++的文件读写有更好的方式,习惯了c的方式了 if(!fp) { printf("error:no such file"); exit(-1); } fflush(fp); int n = fread(buf,sizeof(char),BUF_SIZE,fp); fclose(fp); } void writefile(const char *filename,char *buf) { FILE* fp = fopen(filename,"wb"); //改成wb之后正常了...不然会在每个行尾多回车换行写入 if(!fp) { printf("error:no such file"); exit(-1); } fwrite(buf,sizeof(char),strlen(buf),fp); fclose(fp); } bool printable(char ch) { if(ch >= 'a' && ch <= 'z') return true; if(ch >= 'A' && ch <= 'Z') return true; if(ch >= '0' && ch <= '9') return true; if(ch == ')' || ch == ';') return true; return false;} void analy(char *buf) { bool sinQuoteFlag = false, douQuoteFlag = false; bool valid = false; int line = 0; char chtmp = 0x00; int rightSide = 0; int placeMark[3] = {-1, -1, -1};//标记位置:分别')'、'('、'('左边第一个可打印字符的位置 char dbgstring[DBG_LENGTH]=""; //外层循环,遍历所有字符 for(int i=2; i < BUF_SIZE; i++) { chtmp = buf[i]; if(buf[i] == '\n') line++; //排除单引号和双引号之内的'{',不考虑\'转义的情况和在注释中的情况。然而要能实际中使用,这点无法避免,需要借助编译器的源码。 if(buf[i] == '\'') sinQuoteFlag = !sinQuoteFlag; if(buf[i] == '\"') douQuoteFlag = !douQuoteFlag; if(sinQuoteFlag || douQuoteFlag) continue; if(buf[i] == '{') { //调试语句 for(int k=0;k < DBG_LENGTH-1; k++) { dbgstring[k]=buf[i+k]; } printf("%d-----%s-----------^",i,dbgstring); //调试语句 //debugPlace.push_back(i+1); valid = true; placeMark[0] = -1; placeMark[1] = -1; placeMark[2] = -1; //回溯排除前导非')' for(int j=i-1; j>=0; j--) { if( !printable(buf[j]) ) continue; //')'的位置 placeMark[0] = j; break; } //未找到,则跳过本次'{'的考察 if(placeMark[0] < 1 || buf[placeMark[0]] != ')') continue; else { //记载多余右括号的数目以方便找到最外层的左括号,回溯考察字符串,遇到一次左括号则减一 rightSide = 1; //排除是for/while/do/switch/关键字 for(int k=placeMark[0]-1; k>=1; k--) { //')'前出现单双引号直接认为不是函数头,不考虑有注释的情况 if( buf[k] == '\'' || buf[k] == '\"') { valid = false; break; } if( buf[k] == ')' ) rightSide++; if( buf[k] == '(' ) rightSide--; if( rightSide) continue; //'('的位置 placeMark[1] = k; break; } } if(placeMark[1]<=1) continue; //回溯排除前导非printable for(int l=placeMark[1]-1; l>=0; l--) { if( !printable(buf[l]) ) continue; //'('左边的第一个可打印字符的位置 placeMark[2] = l; break; } if(placeMark[2] < 0) continue; if(placeMark[2] >= IF_LENGTH) { if(buf[placeMark[2]] == 'f' && buf[placeMark[2]-1] == 'i') { if(!printable(buf[placeMark[2]-2])) { continue; } } } if(placeMark[2] >= FOR_LENGTH) { if(buf[placeMark[2]] == 'r' && buf[placeMark[2]-1] == 'o' && buf[placeMark[2]-2] == 'f') { if(!printable(buf[placeMark[2]-3])) { continue; } } } if(placeMark[2] >= WHILE_LENGTH) { if( buf[placeMark[2]] == 'e' && buf[placeMark[2]-1] == 'l' && buf[placeMark[2]-2] == 'i' && buf[placeMark[2]-3] == 'h' && buf[placeMark[2]-4] == 'w' ) { if( !printable(buf[placeMark[2]-5]) ) { continue; } } } if(placeMark[2] >= SWITCH_LENGTH) { if( buf[placeMark[2]] == 'h' && buf[placeMark[2]-1] == 'c' && buf[placeMark[2]-2] == 't' && buf[placeMark[2]-3] == 'i' && buf[placeMark[2]-4] == 'w' && buf[placeMark[2]-5] == 's' ) { if(!printable(buf[placeMark[2]-6])) { continue; } } } if(valid) { debugPlace.push_back(i+1);//换算成从1开始的索引值,也就是到'{'的字符串的长度,包括'{' } }//if(buf[i] == '{') }//for(int i=0; i<sizeof(buf); i++)} void edit(char *buf) { if(!debugPlace.size()) return; char tmp[BUF_SIZE]; memset(tmp,0,sizeof(tmp)); int segLength = 0; memcpy( tmp, buf, debugPlace[0]); memcpy( tmp + debugPlace[0], debugSentence, strlen(debugSentence)); for(unsigned int i=1;i<debugPlace.size();i++) { segLength = debugPlace[i] - debugPlace[i-1] ; //拷贝片段 memcpy( tmp + i * strlen(debugSentence) + debugPlace[i-1] , buf + debugPlace[i-1] , segLength); //拷贝调试语句 memcpy( tmp + i * strlen(debugSentence) + debugPlace[i-1] + segLength , debugSentence, strlen(debugSentence)); //最后一个调试语句插入之后的,拷贝之后的片段 if(i == debugPlace.size() - 1) { memcpy(tmp + (i + 1) * strlen(debugSentence) + debugPlace[i] , buf + debugPlace[i], strlen(buf) - debugPlace[i]); } } memcpy(buf,tmp,strlen(tmp)); } void main(int argc,char *argv[]) { if(argc < 2) { printf("The cmd format is : \n\ dbghead filename1 filename2 filename3 ...."); return; } char buf[BUF_SIZE]; for(int i=1;i<argc;i++) { memset(buf,0,sizeof(buf)); readfile(argv[i],buf); analy(buf); edit(buf); writefile(argv[i],buf); } }
- 给函数增加debug头(一)
- 给函数增加Debug头(二)
- 给函数增加Debug头(三)
- 给函数增加Debug头(四)
- 给函数增加Debug头 java新闻 贪吃蛇c语言(个人经历)
- 给函数增加Debug头 - windows平台的普通打印调试处理
- 给Autoconf增加调式选项-enable-debug(zz)
- 给Autoconf增加调式选项-enable-debug
- 通过代码给IIS增加主机头
- 通过代码给IIS增加主机头
- 给xml文件增加DTD头
- 给std::string增加format函数
- 给std::string增加format函数
- 通过函数给指针赋值(一)
- smarty中的自定义函数(一)assign、cycle、debug...
- debug心得(一)
- C++ 一些常用的函数以及头文件(一)
- NSIS 文本函数头文件介绍(一)
- 如何使网页播放视频
- POJ 3683 2-sat 输出解
- Jquery Datepicker使用
- 嵌入式交叉编译开发环境的搭建步骤(arm-linux)
- Android自定义SeekBar滑动条
- 给函数增加debug头(一)
- JNI 的 call<>method 与 callNonVirtual<>method
- s3c2410嵌入式(带系统)直接操作芯片引脚
- android中git的使用
- prepareCall()方法调用存储过程
- Nature、Science、Cell、Plos系列顶级学术杂志解析
- css设置表格奇偶行背景色
- php的安全字符串类
- vector之迭代初窥