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

全部博文(493)

文章存档

2010年(493)

分类:

2010-05-12 19:19:00

1 现象:问题描述
   CAS业务后台处理程序处理非法操作请求码时,打印的错误日志不全。在输入码流文件中手工构造一个尾结束符'\0'作为operateflag的值,casagent写日志不完整,如下:
[14:17:02] [ERROR] CASUpdate::Process(), user(13903000004), OperateFlag(
2 关键过程:根本原因分析
检查打印此日志部分的代码:
int TCASUpdate::Process(TBusiControlList & BusiCtrlList)
{
    …
    switch(BusiCtrlList.m_cOperateFlag)
    {
             case '2':    //删除标识
            if(0!=BusiCtrlRec.Delete(BusiCtrlList.m_szMsisdn)
               || 0!=BusiCtrlListRec.Delete(BusiCtrlList.m_szMsisdn))
            {
                …
             }
             …
      case '1':  //更新标识
            rv = BusiCtrlRec.Select(BusiCtrlList.m_szMsisdn,oldtypeset);
            …
        default:
            EXEC SQL rollback work;
            WriteLog(LOG_ERROR, "CASUpdate::Process(), user(%s), OperateFlag(%c) is illegal!\n",  BusiCtrlList.m_szMsisdn, BusiCtrlList.m_cOperateFlag);               
            return 2; 
     }
}
WriteLog 函数中调用了如下代码:
   va_list tVal;
   szItem[MAX_LEN_LOGITEM] = 0;
   …
    // 将变参按格式输出到日志项字符串中
    vsnprintf(szItem, MAX_LEN_LOGITEM, sFormat, tVal);
将格式化字符串打印到字符数组变量中,然后打印到文件中,除了接收可变列表va_list 作为参数外,vsnprintf和sprintf功能相同。由于%c 对应的变量为'\0',可以看到打印到字符串变量szItem中包含了'\0',从而使得后面的内容看不到了('\0'作为了字符串的结束符)。
可以使用如下代码验证:
   char szTmp[100] = "abc";
   char c = 0;
   sprintf(szTmp,"%c is number 0", c);
   printf("%s\n",szTmp);
如上代码打印将时一个空行,没有打印出包含 "is number 0"的内容。
但我们直接使用printf时不会出现这样的问题:
   char c = 0;
  printf("'%c' is number 0", c);
如上代码打印出的是 "'' is number 0" .
3 结论:解决方案及效果
实际应用中操作码都是从字符中解析出的,因此不会出现\0的情况,但为了程序的健壮性。增加异常处理:
   if (0 == BusiCtrlList.m_cOperateFlag)
   {
        WriteLog(LOG_ERROR, "CASUpdate::Process(), user(%s), OperateFlag =0x00 is illegal!\n",  BusiCtrlList.m_szMsisdn)
   }
  else
 {
       WriteLog(LOG_ERROR, "CASUpdate::Process(), user(%s), OperateFlag(%c) is illegal!\n",  BusiCtrlList.m_szMsisdn, BusiCtrlList.m_cOperateFlag);
  }
4 经验总结:预防措施和规范建议
sprintf 使用%c 格式打印单个字符时需要注意,如果字符变量为'\0'时,将在打印的字符串变量中赋一个字符串结束符'\0',导致后面的打印被截断了。
5 备注
6 考核点
sprintf使用%c打印char 变量时要注意变量为'\0'的情况。
7 试题
如下代码打印的结果是:B
   char szTmp[100] = "abc";
   char c = 0;
   sprintf(szTmp,"'%c' is number 0", c);
   printf("%s\n",szTmp);

A) '' is number 0
B) '
C) abc
D) '0' is number 0
阅读(317) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~