Focus on ACE

订阅 ace-china
电子邮件:
浏览存于 groups.google.com 上的所有帖子

C++博客 首页 新随笔 联系 聚合 管理
  64 Posts :: 3 Stories :: 22 Comments :: 0 Trackbacks


在Huihoo的ACE论坛中,有一网友问到为什么ACE_Time_Value的秒数在Debug版本少一秒,而
在Release版本上“正常”。经过对其代码的复读以及对ACE的跟踪,发现原来是编码不规范犯
下的一个很严重的错误造成的。本文就讨论这一例子。

以下引用
 

 1 /*
 2 我写了个从年月日时分秒数值得到ACE_Time_Value结果的函数:
 3 */
 4 long s_get_ace_datetime(ACE_Time_Value & ace_datetime,
 5       int year,
 6       int month,
 7       int day,
 8       int hour,
 9       int min,
10       int sec)
11 {
12     if(year<1970 || year>2038 || month<1 || month>12 || day<1 || day>31 ||
13         hour<0 || hour>23 || min<0 || min>59 || sec<0 || sec>59)
14           ACE_ERROR_RETURN((LM_ERROR,
15                          ACE_TEXT("%I(日期时间参数溢出合理的习惯日期时间范围1970.1.2-2038.1.18)n")),-1);
16     timespec_t spec_t;
17     tm time_tm; 
18   time_tm.tm_year=year-1900;
19   time_tm.tm_mon=month-1;
20   time_tm.tm_mday=day;
21   time_tm.tm_hour=hour;
22   time_tm.tm_min=min;
23   #if defined (ACE_NDEBUG)
24     time_tm.tm_sec=sec;
25   #else
26     time_tm.tm_sec=sec+1//奇怪,当由各部分数量构造ACE_Time_Value时,debug编译时,秒的数量总是自动减1,在此要补上1
27   #endif
28    spec_t.tv_sec=mktime(&time_tm); 
29    if(spec_t.tv_sec<0)
30    ACE_ERROR_RETURN((LM_ERROR,ACE_TEXT("%I(日期时间转化错误,得到<0的time_t,日期范围是1970.1.2-2038.1.18)n")),-1);
31    ace_datetime.set(spec_t);
32    return 0;
33 }
34 /*
35 我在VC++7.1上分别编译了Debug版本和Release版本,time_tm.tm_sec竟然会有一秒的差别,莫名其妙地影响了我的项目.
36 哪位高手知道为什么?
37 另外ACE_Time_Value的范围太小,ACE中是否有大日期时间范围的其它类封装?
38 */

以下是我的回贴:

你这个问题还真有趣,我跟踪了ACE相关代码后才发现,问题原来出在你写的函数中,病因是,使用未完全初始化的结构体变量

timespec_t spec_t;
后面加上语句
memset(
&spec_t ,0,sizeof(timespec_t));
即可

局部变量 spec_t 在debug时,各字段均被初始化为0xCCCCCCCC,它是一个负数
在下面的操作中,只修改了tv_sec,而tv_nsec 仍为一个负数
spec_t.tv_sec=mktime(
&time_tm ); 


ACE_Time_Value::normalize()默默地为你作了规格化处理,就替你减去了一秒钟。





原代码更严重的错误在于:
原以为 Release版本是“正常”的,其实不然,而是Release隐藏了更严重的错误。
严重是因为它表现出错误的时候很随机,一旦产品发布,很难发现。

// 对象(结构体)timespec有两个公有属性
 typedef  struct  timespec
     
{
       time_t tv_sec; 
//  Seconds
        long  tv_nsec;  //  Nanoseconds, 十亿分之一秒
     }
 timespec_t;
     

在原代码16行
timespec_t spec_t;
构造了一个 timespec_t  临时对象spec_t后,debug版把它各字段初始化为 0xcccccccc,这使得问题一下子得于曝光.而Release版本, spec_t 为一个随机值. 本例程中,不允许 spec_t的tv_nsec为非0的任何数,为正常尽管看上去没有问题,但是这个对应的ACE_Time_Value的值也不可靠.在特定情况下可能产生重大事故.

C++编码规范:
初始化对象时要完全。

声明一个结构体后,如果要对其初始化,建议先把它设为0之后再作后续操作,养成这样一个习惯,就不会出现这样郁闷的事了。


原贴出处:
http://www.huihoo.com/forum/viewthread.php?tid=11016


mooyee

posted on 2006-04-11 15:29 Stone Jiang 阅读(1333) 评论(1)  编辑 收藏 引用 所属分类: ACEC++&OOP

Feedback

# re: C++编码不规范出现的错误一例的解析 2010-07-01 09:41 mymtom
sec<0 || sec>59
是不对的.应该是
sec<0 || sec>60
  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理