首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言時間函數陷阱深度揭秘:localtime/asctime 靜態內部緩衝區導致的數據覆蓋問題

     編輯:關於C語言

陷阱現場:三次 localtime 卻得到相同時間

time_t t1 = time(NULL); sleep(3); time_t t2 = time(NULL);
struct tm *tm1 = localtime(&t1);
struct tm *tm2 = localtime(&t2);
struct tm *tm3 = localtime(&t1);  // 本意獲取 t1 時間

printf("tm1=%p tm2=%p tm3=%p\n", tm1, tm2, tm3);  // 三者地址相同!
printf("%s", asctime(tm1));  // 輸出 t2 時間
printf("%s", asctime(tm2));  // 輸出 t2 時間
printf("%s", asctime(tm3));  // 輸出 t2 時間

根因:localtime 使用靜態內部 struct tm

每次調用覆蓋同一塊靜態內存,返回同一地址。後續調用 asctime 時傳入的均為最新值指針。

解決方案:本地結構體拷貝

struct tm tm4 = *localtime(&t1);  // 解引用拷貝
struct tm tm5 = *localtime(&t2);
printf("tm4=%p tm5=%p\n", &tm4, &tm5);  // 不同地址
printf("tm4.sec=%d tm5.sec=%d\n", tm4.tm_sec, tm5.tm_sec);  // 正確秒數

連環陷阱:asctime 也用靜態字符數組

printf("%s%s", asctime(&tm4), asctime(&tm5));  // 連續調用
// 第一參數 asctime(&tm4) 更新靜態緩衝區為 tm4 時間
// 第二參數 asctime(&tm5) 覆蓋為 tm5 時間
// printf 讀取兩個參數時,緩衝區已是 tm5 時間 → 兩次輸出相同

正確做法:調用後立即使用/拷貝

printf("%s", asctime(&tm4));  // 立即輸出 tm4
printf("%s", asctime(&tm5));  // 立即輸出 tm5

// 或拷貝到本地字符數組
char buf1[26], buf2[26];
strcpy(buf1, asctime(&tm4));
strcpy(buf2, asctime(&tm5));

POSIX 規範的四大「靜態返回」函數

函數返回類型風險
localtimestruct tm *靜態結構體被覆蓋
gmtimestruct tm *同上
asctimechar *靜態字符數組被覆蓋
ctimechar *同上

最佳實踐

  1. 不需保存結果:調用後立即打印/使用
  2. 需保存結果:拷貝到本地變量(結構體/字符數組)
  3. 多線程環境:使用 localtime_r/gmtime_r/asctime_r/ctime_r 可重入版本
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved