1 现象:问题描述
AIX操作系统,产品A开始运行后,停了一段时间才开始进行呼叫,但系统不接收任何呼叫。经过一段时间后,系统恢愎正常,可以接入呼叫。这段时间不定有多长,可能几十秒,也可能半个多小时。
2 关键过程:根本原因分析
由于GetTickCount函数是在头文件中使用inline函数实现,其中使用了静态变量。inline函数中的变量应该是在第一次调用时被初始化,但AIX VAC 6.0编译器处理此情况时存在Bug:只要是某个cpp文件中第一次调用,都将inline函数中的静态变量初始化一遍。结果导致呼叫进来后,GetTickCount函数中记录时间的变量被重新初始化,这样所有的事件超时时间都被延长。此延长的时间取决于第一次执行GetTickCount函数的时间与呼叫进入后执行GetTickCount函数的时间差。
以下是GetTickCount函数的实现:
gettickcount.h
/*******************************************************************************
Desc : 将timeval封装成类,在变量被定义时自动调用构造函数取得系统时间
*******************************************************************************/
class CTime_INFOX
{
friend DWORD ICD_GetTickCount();
public:
CTime_INFOX()
{
struct timespec tp;
clock_gettime(CLOCK_REALTIME,&tp);
tv_sec = tp.tv_sec;
tv_nsec = tp.tv_nsec;
}
private:
unsigned long tv_sec;
long tv_nsec;
};
inline DWORD ICD_GetTickCount()
{
static CTime_INFOX starttime; // 静态变量,程序启动时调用构造函数,保存程序启动时间
// 计算当前时间与系统启动时间的差
struct timespec tp;
clock_gettime(CLOCK_REALTIME,&tp);
//时间回调到启动之前将导致时间定时器无法触发问题修改
if (tp.tv_sec < starttime.tv_sec)
{
starttime.tv_sec = tp.tv_sec;
starttime.tv_nsec = tp.tv_nsec;
}
return ((tp.tv_sec - starttime.tv_sec)*1000 + (tp.tv_nsec - starttime.tv_nsec)/1000000);
};
3 结论:解决方案及效果
将GetTickCount函数实现放在cpp文件中,不在头文件中使用inline函数来实现。问题解决。
4 经验总结:预防措施和规范建议
AIX VAC 6.0编译器不能在inline函数中使用static变量,否则会导致不可预期的程序行为。AIX VAC 7.0编译器已解决了此问题。HP下的编译器未发现类似现象。
5 备注
NA
6 考核点
AIX VAC 6.0编译器存在的bug
7 试题
以下哪个编译器在inline函数中使用static变量,static变量可能会被初始化多次?(B)
A. HP ANSI C++ B3910B A.03.55
B. AIX VAC 6.0
C. AIX VAC 7.0
D. 以上所有编译器
阅读(774) | 评论(0) | 转发(0) |