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

全部博文(493)

文章存档

2010年(493)

分类:

2010-05-12 19:13:55

1 现象:问题描述
A局点某个IUSER版本上网后,IUSERBILL批量处理程序,不能每天根据basetab_pps表号码刷新msisdn号码清单。
2 关键过程:根本原因分析
经定位,出现问题的代码如下:
int TMsisdnList::GetMsisdn(TChainNode* &pCurNode,     int &handle, char* pMsisdn)
{
    time_t now = 0;
    struct tm *tf;
    struct tm *lo;
    int ret = 0;
    HMSISDN tMsisdn;  
    // 当前时间与m_LastOpenTime相比跨天,重新初始化list
    (int)time( &now );
    if( ret == -1 )
    {
        WriteLog("TMsisdnList::GetMsisdn():failed to get system time.\n");
        return -1;  
    }
   
    tf = localtime( &now );    
    lo = localtime( &m_LastOpenTime );
          
    if(lo->tm_mday != tf->tm_mday)
    {
     InitChain();
    }
    …
}
问题出在红色代码:调用localtime后,lo和tf指向同一个地址空间。
系统函数 struct tm *localtime(const time_t *timer);
返回的是一个指向tm 结构的指针,也就是指向某个变量(这个变量是localtime系统调用使用的内部 static变量)。再调用一次此函数后,这个静态变量的值被修改了,而原来的指针tm * tf指向的是这个变量,所以*tf内容就被修改了。导致判断跨天的条件(lo->tm_mday != tf->tm_mday) 恒为假。
实际应该使用函数返回指向的值,而不能使用指针,否则会指向同一地址从而使用了被修改的值。
3 结论:解决方案及效果
正确方法为,调用localtime后将指针指向的值保存到变量中:
struct tm tf;
struct tm lo;
tf = *localtime( &now );    
lo = *localtime( &m_LastOpenTime );
4 经验总结:预防措施和规范建议
localtime()系统调用返回的是指向函数内部的static变量的指针,每次调用都会修改此static变量的值。如果使用指针接收返回值,则后面的调用会修改前面调用的指针指向的值。调用此函数后需要将指针指向的内容保存以供使用。
由于localtime使用了函数内部的static变量,对于多线程的环境需要使用线程安全函数localtime_r(struct tm *localtime_r(const time_t *restrict clock,  struct tm *restrict res);)来代替。

5 备注
6 考核点
指针指向的变量值改变后,其他指向该变量的指针引用的值也相应变化。
7 试题
1.系统函数localtime 定义为: struct tm *localtime(const time_t *timer); 调用此函数将time_t 类型的时间转换为tm结构的当地时间,返回指针指向函数内部的静态变量。tm结构的主要成员定义如下:
     int   tm_sec;    /* seconds after the minute - [0, 60] */
                      /* for leap seconds */
     int   tm_min;    /* minutes after the hour - [0, 59] */
     int   tm_hour;   /* hour since midnight - [0, 23] */
     int   tm_mday;   /* day of the month - [1, 31] */
     int   tm_mon;    /* months since January - [0, 11] */
     int   tm_year;   /* years since 1900 */
     int   tm_wday;   /* days since Sunday - [0, 6] */
假设变量now为当天的时间,lastDayTime为上一天的时间:
time_t  now = time(NULL);
time_t  lastDayTime = now - (24*60*60) ;  // 上一天的时间
那么执行如下程序片断后,结果为: (B)
tm * pLastDay = localtime(&lastDayTime);
tm * pCurrentDay = localtime(&now);
if (pLastDay->tm_mday == pCurrentDay->tm_mday)
{
    printf("same day of month!\n");
}
else if (pLastDay->tm_mday < pCurrentDay->tm_mday)
{
    printf("last day < current day!\n");
}
else
{
    printf("last day > current day!\n");
}
A  由于可能跨月,打印结果不确定。
B  打印:same day of month!
C  打印:last day < current day!
D 打印:last day > current day!
阅读(758) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~