避免對空指針進行賦值操做時內存崩潰方法:數據庫
char netdb[1024] = {0};定義數組常量數組
char *netdebug = netdb;把數組指針賦值給字符串指針,這樣字符串指針就不是空指針了,避免了空指針操做。函數
fseek(fp, 0, 2);debug
acklen = ftell(fp);指針
fseek(fp, 0, 0); 求文件指針的指向的文件的大小調試
/*執行結果寫進ackuf */server
if((fgets(ackbuf, acklen, fp)) ==NULL ) fgets函數一次只能讀取一行內存
{rem
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);