簡體   English   中英

當傳遞值 >0x7FFFFFFF 時 localtime() 崩潰

[英]localtime() crashes when pass value >0x7FFFFFFF

根據我的理解time_t rawtime = 0xffFFffFFGMT: Sunday, February 7, 2106 6:28:15 AM

但是下面的程序在某些編譯器中帶來了Thu 1970-01-01 02:59:59 MSK ,而在其他編譯器中則崩潰了。

int main() 
{

    time_t rawtime = 0xffFFffFF;
    struct tm  ts;
    char       buf[80];

    ts = *localtime(&rawtime);
    strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", &ts);
    printf("%s\n", buf);
    return 0;
}

rawtime >0x7fFFffFF時出現錯誤行為。 為什么? 如何解決這個問題?

UPD:我需要有一系列警報並在時機成熟時采取行動。 這是嵌入式系統,我無法忍受 memory 和復雜數據類型的資源。

在大多數平台上,類型time_t是簽名的 integer。 同樣在大多數平台上, time_t從 1970 年 1 月 1 日開始計算時間。結合這兩個事實,我們有對應於 1970 年 1 月 1 日之前的日期的負time_t值。

如果你機器上的time_t是一個有符號的 32 位 integer, 0xffffffff是 -1。 因此,理論上,該值對應於 1969 年 12 月 31 日的 23:59:59 UTC,即 UTC 午夜前一秒。 但在某些情況下,-1 表示錯誤。 因此,盡管我從未遇到過它,但如果有一個localtime()實現將輸入的值 -1 視為錯誤,我並不完全感到驚訝。

你說它“崩潰了”,但這部分是你的錯。 localtime通過返回 null 指針來指示失敗。 所以寫起來更安全

struct tm *ts;

ts = localtime(&rawtime);
if(ts == NULL) {
    fprintf(stderr, "localtime failed\n");
    exit(1);
}

strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S %Z", ts);

如果time_t是帶符號的 32 位值,則其最大值為 2147483647(仍假設 Unix 時期為 1970 年)對應於 2038 年 1 月 19 日 03:14:07 UTC。 最小值 2147483648 對應於 1901 年 12 月 13 日 20:45:52 UTC。

沒錯,如果time_t被視為無符號,則最大 32 位值將是 4294967295 並且對應於您提到的 2106 中的日期和時間。

如果time_t是 64 位類型,並且越來越流行(為了防止y2.038k 問題或多或少有必要),則最大值是如此之大以至於它實際上毫無意義。 (它太大了,年份甚至不能用 32 位表示。)

最后,值得記住的是time_t的解釋是特定於平台的。 從理論上講,它不一定要計算秒數,不一定要從 1970 年 1 月 1 日開始計算,甚至不一定是 integer。 即使這些事實確實成立,也沒有規定必須time_t進行簽名,因此在為廣泛可移植性而設計的程序中,我不會指望有對應於 1901-1970 的值,因為在某些平台上它們可能對應於畢竟是 2038-2106 年。

time_t的類型和范圍是實現定義的,沒有最低要求。 它可以是有符號、無符號、32 位、64 位、浮點等。

如果您使用的編譯器沒有time_t其范圍符合您的要求,您可以:

  • 使用不同的編譯器,或
  • 避免使用time_t ,或
  • 重組您的程序以在編譯器的time_t限制內工作。

正如評論中提到的,“崩潰”可能是由於本地時間由於輸入超出范圍而返回localtime指針,並且您在沒有首先檢查 null 的情況下取消引用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM