微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

localtime() 在传递值 >0x7FFFFFFF 时崩溃

如何解决localtime() 在传递值 >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 时出现错误行为。为什么?如何解决这个问题?

更新: 我需要有一系列警报,并在时机成熟时采取行动。这是嵌入式系统,我不能为复杂的数据类型占用内存和资源。

解决方法

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

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

你说它“崩溃了”,但这部分是你的错。 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 年的日期和时间。

如果 time_t 是 64 位类型,因为它越来越流行(并且或多或少是为了阻止 y2.038k problem 的必要性),最大值太大以至于实际上毫无意义。 (它太大了以至于年份甚至无法用 32 位表示。)

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

,

time_t 的类型和范围是实现定义的,没有最低要求。可以是有符号、无符号、32 位、64 位、浮点等。

如果您使用的编译器没有范围满足您要求的 time_t,您可以:

  • 使用不同的编译器,或
  • 避免使用time_t,或
  • 重构您的程序,使其在编译器的 time_t 限制范围内工作。

正如评论中提到的,“崩溃”很可能是由于 localtime 由于输入超出范围而返回空指针,并且您在没有首先检查空值的情况下取消引用它。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。