今天寫某個程式時,出現一個奇妙的問題,輸出的時間戳總是不正確,查了半天百思不得其解。我把出問題的代碼簡化成下面的形式:
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
你竟然解决了,狂拽酷炫吊炸天