编程基础及技巧
避免对空指针进行赋值操作时内存崩溃方法:
char netdb[1024] = {0};定义数组常量
char *netdebug = netdb;把数组指针赋值给字符串指针,这样字符串指针就不是空指针了,避免了空指针操作。
fseek(fp, 0, 2);
acklen = ftell(fp);
fseek(fp, 0, 0); 求文件指针的指向的文件的大小
/*执行结果写进ackuf */
if((fgets(ackbuf, acklen, fp)) ==NULL ) fgets函数一次只能读取一行
{
ackstatus = ERR_CLIREQ;
goto Err;
}
调试语句,加在你认为可能出错的地方,例如:
fprintf(stderr, "00000000000000000000:%s\n", tmp);
fprintf(stderr, "222222222222222222222222:%d\n", acklen);
if(!strncmp(tmp, "0", strlen(tmp))) 判断字符串是否是0,这种用法很繁琐,可以用下面的指令:
if(tmp[0] == '0')
char netto[1024] = {0};
char *nettool = netto;
char *nettooldef = netto;两个字符串指针指向的是同一个内存地址,无论是对nettool操作还是对nettooldef操作,都是对同一个内存地址进行操作。还是没有避免混淆。
正确用法:
char netto[1024] = {0};
char nettodef[1024] = {0};
char *nettool = netto;
char *nettooldef = nettodef;
strncat("ping -c 3", tmp, strlen(tmp));这种用法是错误的,extern char *strncat(char *dest,char *src,int n); dest是一个指针变量,代表内存地址,不应该是常量。正确用法如下:
char ping[20] = "ping -c 3";
strncat(ping, tmp, strlen(tmp));
fseek(fp, 0, 2);
acklen = ftell(fp);
fseek(fp, 0, 0);
ackbuf = (char *)malloc(acklen);
/*执行结果写进ackuf */
if((fread(ackbuf, 1, acklen, fp)) != acklen ) 这样管道获取acklen是错误的。解决方法如下
while(!feof(fp) && (++acount_buf))
{
/* strlen入参不能为空指针!!!!!!!!!!!!!!!!!,故改用acount_buf */
ackbuf = (unsigned char *)realloc(ackbuf, acount_buf * BUF_SIZE);
if(!ackbuf)
{
ackstatus = ERR_CLIREQ;
goto Err;
}
fread(ackbuf + strlen(ackbuf), sizeof(char), BUF_SIZE, fp);} 第一次只是给ackbuf分配了内存空间,但是没有赋值,而strlen求的是实际的字符串长度,因此strlen(ackbuf)=0.
/* 标志位 */
tmp = strtok((char *)reqbuf, "\r\n");
switch(tmp[0])
{
case '0':
/* netstat */
snprintf(cmdline, sizeof(cmdline), "%s", NETSTAT_CMD);
break;
case '1':
/* arp */
snprintf(cmdline, sizeof(cmdline), "%s", ARP_CMD);
break;
case '2':
/* ping */
tmp = strtok(NULL, "\r\n");
assert(tmp);
snprintf(cmdline, sizeof(cmdline), "%s%s", PING_CMD, tmp);
break;
case '3':
/* traceroute */
tmp = strtok(NULL, "\r\n");
assert(tmp);
snprintf(cmdline, sizeof(cmdline), "%s%s", TRACEROUTE_CMD, tmp);
break;
case '4':
/* nmap */
tmp = strtok(NULL, "\r\n");
assert(tmp);
snprintf(cmdline, sizeof(cmdline), "%s%s", NMAP_CMD, tmp);
break;
default :
/* other error!! */
ackstatus = ERR_CLIREQ;
goto Err;
}
这段程序很是繁琐,修改如下:
tmp = strtok((char *)reqbuf, "\r\n");
cmdnum = atoi(tmp);
/* 容错处理 */
if(cmdnum < 0 || cmdnum >4)
{
ackstatus = ERR_CLIREQ;
goto Err;
}
/* 命令参数 */
tmp = strtok(NULL, "\r\n");
snprintf(cmdline, sizeof(cmdline), "%s%s", cmdbuf[cmdnum], tmp ? tmp : "");
snprintf(cmdline, sizeof(cmdline), "%s%s", cmdbuf[cmdnum], tmp ? tmp : null);
编译出错,null没有内存地址,snprintf出错。修改如下:
snprintf(cmdline, sizeof(cmdline), "%s%s", cmdbuf[cmdnum], tmp ? tmp : "");
char *tmp = NULL;
tmp = strtok((char *)cmdline, "\r\n"); 不需要给tmp提前分配内存,因为tmp只是和strtok指向同一个内存空间。
调试语句的使用技巧,使用#if 1 #endif 1:
#if 1(0表示永远都不会成立的一个条件,这样这段代码就不会编译了,1表示永远都成立的条件)
char test[] = "192.168.51.206\r\n21\r\nftp\r\n123456\r\nDIRECTORY\r\n\r\n";
reqbuf = (char *)test;
#endif
makecert.c:
struct iw_key_struct
{
char crtname[64];
char commoname[64];
char country[4];
…….
}
…..
tmp=China;
sprintf(keystr->country,"%s\n",tmp);
程序执行错误,修改char country[10]之后,没有问题了。使用sprintf时,格式化数据大小必须小于字符缓冲区大小。
#define MAKEKEYPATH "/home/xiachengjiao/nnba/nnba/mise/calls/engine/key/"
snprintf(cmdline, sizeof(cmdline), "mkdir %sdemoCA 1>/dev/null 2>&1", MAKEKEYPATH);
retval = iw_system(cmdline);
指令执行错误,因为/engine/key/demoCA/之前不存在,所以mkdir需要加参数-p。正确写法:
snprintf(cmdline, sizeof(cmdline), "mkdir –p %sdemoCA 1>/dev/null 2>&1", MAKEKEYPATH);
snprintf(cmdline, sizeof(cmdline), "select keyname from server.ww_cert_t where keyname='%s'", keyname);
snprintf的用法是挺巧妙的,如上。
char **res = NULL;
int retval = 0;
DEBUGLOG(IW_LOG_MAINBRANCE, DEBUG, "keyname=%s,endtime=%s,remark=%s\n", keyname, endtime, remark);
/* 判断数据库表中证书名称是否重复 */
snprintf(cmdline, sizeof(cmdline), "select keyname from server.ww_cert_t where keyname='%s'", keyname);
DEBUGLOG(IW_LOG_MAINBRANCE, DEBUG, "cmdline=%s\n", cmdline);
retval = iw_db_select(cmdline, res);
DEBUGLOG(IW_LOG_MAINBRANCE, DEBUG, "retval=%d,*res=%s\n", retval,* res);
程序段错误,下面程序正确的。
char *res = NULL;
int retval = 0;
DEBUGLOG(IW_LOG_MAINBRANCE, DEBUG, "keyname=%s,endtime=%s,remark=%s\n", keyname, endtime, remark);
/* 判断数据库表中证书名称是否重复 */
snprintf(cmdline, sizeof(cmdline), "select keyname from server.ww_cert_t where keyname='%s'", keyname);
DEBUGLOG(IW_LOG_MAINBRANCE, DEBUG, "cmdline=%s\n", cmdline);
retval = iw_db_select(cmdline, &res);
DEBUGLOG(IW_LOG_MAINBRANCE, DEBUG, "retval=%d,res=%s\n", retval, res);