1 现象:问题描述
A局点SMP1/2的smptblmnt(SMP的过期数据库数据清理程序)运行产生core
2 关键过程:根本原因分析
由core定位:由过期数据删除程序smptblmnt产生,core产生调试信息有限:
(gdb) where
#0 0xc04256a8 in _doprnt () from /usr/lib/libc.1
#1 0xc041d2d8 in printf () from /usr/lib/libc.1
#2 0xb654 in UpdateConfig () from /home/smpgd/temp/smptblmnt
#3 0xc704 in main () from /home/smpgd/temp/smptblmnt
可以确定在UpdateConfig()函数中调用printf产生core,检查UpdateConfig()代码,有3个地方调用printf():
printf("ERROR:Query min date from table %s error!,errorno=%s\n",
CI[TabNo].TabName,SQLCODE);
printf("ERROR:Query max date from table %s error!,errorno=%s\n",
CI[TabNo].TabName,SQLCODE);
printf("Update smp_reportcfg:%s\n", SqlStr);
从中可以看出,前面2个的使用存在问题:SQLCODE为整数,应当使用%d打印,这里使用%s。
为了验证这个问题,我写了一个测试test.c
#include
void main(void)
{
int aaa = 111;
printf("result=%d\n", aaa);
printf("result=%s\n", aaa);
}
编译后执行,输出为:
result=111
result=
将test.c的整数改为负值
#include
void main(void)
{
int aaa = -111;
printf("result=%d\n", aaa);
printf("result=%s\n", aaa);
}
编译执行,core
result=-111
Segmentation fault (core dumped)
到这一步,问题已经定位。printf使用格式%s打印时表示打印此变量指向的字符串,打印负值的数值(没有测试浮点型)导致访问非法的地址,会core
3 结论:解决方案及效果
将代码中打印有误的代码改为:
printf("ERROR:Query min date from table %s error!,errorno=%d\n",
CI[TabNo].TabName,SQLCODE);
printf("ERROR:Query max date from table %s error!,errorno=%d\n",
CI[TabNo].TabName,SQLCODE);
4 经验总结:预防措施和规范建议
使用printf打印时%s后面必须是一个有效的地址
5 备注
6 考核点
printf系列函数参数表与传入变量的对应关系。
7 试题
1 如下代码
char szTmp[] = "abcd";
int iTmp = 0;
memcpy(&iTmp,szTmp,sizeof(iTmp));
关于如下语句说明正确的是: (D)
printf("%s, %s", szTmp, iTmp);
A) iTmp是一个整形数,打印出的将是"abcd"的ASCII码表示的整数(不考虑字节序)。
B) 使用%s打印iTmp时,将iTmp解释为字符串,也就是打印出"abcd",
C) 使用%s打印iTmp时,将iTmp解释为字符串,但是由于iTmp只有4位,字符串"abcd"后没有结束符'\0',因此语句会引起错误。
D) 使用%s打印iTmp时,将整数的值解释成字符串的地址,从而可能引起访问非法地址
阅读(226) | 评论(0) | 转发(0) |