Chinaunix首页 | 论坛 | 博客
  • 博客访问: 573861
  • 博文数量: 493
  • 博客积分: 2891
  • 博客等级: 少校
  • 技术积分: 4960
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-17 17:11
文章分类

全部博文(493)

文章存档

2010年(493)

分类:

2010-05-12 18:47:39

1 现象:问题描述
在A版本项目级系统测试中,OMCAgent模块,LICENSE数据不能入库。
2 关键过程:根本原因分析
首先,观察日志发现
Timing processed the FluxDegree insert into database. STATDATE: 2001-04-10 20:00:00 , m_iLowerFluxDegree: 0 , m_iUpperFluxDegree: 0
insert the realFlow to DB Failed
日志打印正确,但入库失败;
dbx跟踪发现各数据正常;
日志输出前增加打印变量至文件,数据仍然正常,且可以入库,但一旦去除调试语句就出现不能入库的情况;经分析,可能是打印文件语句前定义了变量,内存分配发生变化,从而更改了原先出现问题的现象;于是直接用屏幕打印printf发现STATDATE时间在入库前被更改了,仔细检视代码,终查出日志输出变量字符越界造成内存混乱导致入库数据变量被改变以至于SQL语句语法错误从而数据不能入库;
举例如下:
未出现字符越界,内存分配正确,打印结果正确;
int main()
{
    char cmdmsg[16];
    sprintf(cmdmsg,"HelloWorld");
    char msg[16];
    sprintf(msg,"%s12345",cmdmsg);
    printf("==%s==%s==\n",msg,cmdmsg);
    return -1;  
}
结果:==HelloWorld12345==HelloWorld==
 
如若字符越界
int main()
{
    char cmdmsg[16];
    sprintf(cmdmsg,"HelloWorld");
    char msg[16];
    sprintf(msg,"%s12345678",cmdmsg);
    printf("==%s==%s==\n",msg,cmdmsg);
    return -1;  
}
结果:==HelloWorld12345678==78==
如上所述,先给cmdmsg分配字节存放"HelloWorld",然后又给msg分配字节存放
"HelloWorld12345678",由于超出声明2个字节,因此溢出至cmdmsg声明的内存区,但是sprintf函数会在结尾出自动加上结束符'\0',导致cmdmsg被改变,
即:cmdmsg[0] ='7'; cmdmsg[1] ='8'; cmdmsg[2] = '\0';
3 结论:解决方案及效果
由原因分析结果对代码作修改,扩展声明字节空间,并将sprintf函数改为snprintf函数,经测试,问题解决
4 经验总结:预防措施和规范建议
由此可见,此现象既是因字符越界而引起的问题,也体现出sprintf函数的危险性,建议使用snprintf函数;
举例:
int main()
{
    char cmdmsg[16];
 memset(cmdmsg, 0, sizeof(cmdmsg));
    snprintf(cmdmsg,(sizeof(cmdmsg) - 1),"HelloWorld");
    char msg[16];
 memset(msg, 0, sizeof(msg));
  snprintf(msg,(sizeof(msg) - 1),"%s12345678",cmdmsg);
    printf("==%s==%s==\n",msg,cmdmsg);
    return -1;  
}
结果:==HelloWorld12345==HelloWorld==
如若使用snprintf函数,会在自定义的地址加上'\0'结束符,即使发生越界也不至于影响其他内存空间;
5 备注
6 考核点
字符串越界
7 试题
以下程序可能存在问题的是:AB
A.
void Test()
{
 char str1[6];
 sprintf(str1,"test1");
 char str2[6];
 sprintf(str2,"%stest2", str1);
 printf("str1:%s, str2:%s\n", str1, str2);
     return;  
}
B.
void Test()
{
 char str1[6];
 _snprintf(str1, sizeof(str1), "test1");
 char str2[6];
 _snprintf(str2, sizeof(str2), "%stest2", str1);
 printf("str1:%s, str2:%s\n", str1, str2);
     return;  
}
C.
void Test()
{
 char str1[6];
 memset(str1, 0, sizeof(str1));
 _snprintf(str1, (sizeof(str1) -1), "test1");
 char str2[6];
 memset(str2, 0, sizeof(str2));
 _snprintf(str2, (sizeof(str2) - 1), "%stest2", str1);
 printf("str1:%s, str2:%s\n", str1, str2);
     return;  
}
阅读(403) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~