今天写某个程式时,出现一个奇妙的问题,输出的时间戳总是不正确,查了半天百思不得其解。我把出问题的代码简化成下面的形式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include<iostream> #include<time.h> using namespace std; int main(int argc, char *argv[]) { time_t curr_time; curr_time = time(NULL);//得到当前Unix时间戳 struct tm *now; now = localtime(&curr_time);//转换成年月日时分秒到结构体中 printf("debug1::%04d%02d%02d\n",now->tm_year+1900,now->tm_mon+1,now->tm_mday);//目前是8月18日 time_t lastmon_t = curr_time - 1728000;//目前时间前推20天,应该得到的结果是7月29日的时间戳 struct tm *las; las = localtime(&lastmon_t); printf("debug2::%04d%02d%02d\n",now->tm_year+1900,now->tm_mon+1,now->tm_mday);//输出now结构体的时间 printf("debug3::%04d%02d%02d\n",las->tm_year+1900,las->tm_mon+1,las->tm_mday);//输出las结构体的时间 getchar(); return 0; } |
输出结果是:
debug1::20160818
debug2::20160729
debug3::20160729
debug2和debug3的位置本想分别输出目前的时间now和前推的时间las,而结果并没有符合预想。看了看代码,在前一次debug1输出now,和后一次debug2输出now之间,并没有对结构体now做任何赋值操作,而now的内容却改变成了和las一样的。
这个问题让我百思不得其解,怎么看我都没有对now进行操作,唯一的解释就是now和las指针指向的是同一个地址。最后不断的测试缩小范围,把问题锁定到localtime()上。于是上网查询了一下localtime()的文档,发现localtime()不仅不是线程安全的函数,不建议使用,而且只能同时使用一次,因为localtime()不是可重入的。
所以说我的now和las确实指向了同一个地址,因为我是在Linux下编译的所以并没有提示,如果在VS下编译就会看见localtime()不是线程安全函数的提示。于是我从网上找到了libc提供的另一个函数localtime_r(),修改程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include<iostream> #include<time.h> using namespace std; int main(int argc, char *argv[]) { time_t curr_time; curr_time = time(NULL);//得到当前Unix时间戳 struct tm now; localtime_r(&curr_time,&now);//转换成年月日时分秒到结构体中 printf("debug1::%04d%02d%02d\n",now.tm_year+1900,now.tm_mon+1,now.tm_mday);//目前是8月18日 time_t lastmon_t = curr_time - 1728000;//目前时间前推20天,应该得到的结果是7月29日的时间戳 struct tm las; localtime_r(&lastmon_t,&las); printf("debug2::%04d%02d%02d\n",now.tm_year+1900,now.tm_mon+1,now.tm_mday);//输出now结构体的时间 printf("debug3::%04d%02d%02d\n",las.tm_year+1900,las.tm_mon+1,las.tm_mday);//输出las结构体的时间 getchar(); return 0; } |
输出结果是:
debug1::20160818
debug2::20160818
debug3::20160729
于是问题解决了,还有要注意的是,Windows下并没有localtime_r,与其相同的函数是localtime_s。
======
kujou_rin