首页 > 解决方案 > 当传递值 >0x7FFFFFFF 时 localtime() 崩溃

问题描述

根据我的理解 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:我需要有一系列警报并在时机成熟时采取行动。这是嵌入式系统,我无法为复杂的数据类型提供内存和资源。

标签: ctime-t

解决方案


在大多数平台上,类型time_t是有符号整数。同样在大多数平台上time_t,从 1970 年 1 月 1 日开始计算时间。结合这两个事实,我们有time_t对应于1970 年 1 月 1 日之前的日期的负值。

如果time_t在您的机器上是有符号的 32 位整数,0xffffffff则为 -1。因此,理论上,该值对应于 1969 年 12 月 31 日的 23:59:59 UTC,即 UTC 午夜前一秒。但在某些情况下,-1 表示错误。localtime()因此,尽管我从未遇到过它,但如果有一个实现将输入的值 -1视为错误,我并不完全感到惊讶。

你说它“崩溃了”,但这部分是你的错。 localtime通过返回空指针来指示失败。所以写起来更安全

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 中的日期和时间。

如果是 64 位类型,因为它越来越流行(为了防止y2.038k 问题time_t或多或少有必要),最大值是如此之大以至于它实际上毫无意义。(它太大了,年份甚至不能用 32 位表示。)

最后,值得记住的是,解释time_t是特定于平台的。从理论上讲,它不一定要计算秒数,不一定要从 1970 年 1 月 1 日开始计算,甚至不一定是整数。即使这些事实确实成立,也没有规定time_t必须签名,因此在为广泛可移植性而设计的程序中,我不会指望有对应于 1901-1970 的值,因为在某些平台上它们可能对应于 2038毕竟,–2106。


推荐阅读