什么是2038问题?

开发 前端
不知道你有没有听过2038问题?无论你是否听过,本文将带你认识什么是2038问题。

什么是2038问题

不知道你有没有听过2038问题?无论你是否听过,本文将带你认识什么是2038问题。

[[316871]]

Unix时间戳

定义为从格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。

而在C语言中,常用time_t来表示。举个例子:

  1. #include <stdio.h> 
  2. #include <time.h> 
  3. int main (void)  
  4.    time_t rawtime = 10;//time(NULL)获取当前时间戳 
  5.    struct tm info; 
  6.    //转为tm结构 
  7.    localtime_r( &rawtime,&info); 
  8.    //转为字符串 
  9.    printf("时间为: %s\n", asctime(&info)); 
  10.    return 0; 

运行结果:

  1. 时间为: Thu Jan  1 08:00:10 1970 

在这里,我给rawtime设置为10,从打印结果来看也知道是正确的了。(注意,由于我们的时区为东八区,所以得到的时间是八点。)

当然这里的内容暂时不展开,主要关注time_t。

然而实际上,time_t到底是什么?

通常,time_t直接或者间接被定义为下面这样:

  1. typedef long time_t 

我们知道,在32位程序下面,long占用四个字节空间:

  1. #include<stdio.h> 
  2. #include <limits.h> 
  3. int main(void) 
  4.     printf("long size:%zd\n",sizeof(long)); 
  5.     printf("long max:%ld\n",LONG_MAX); 
  6.     return 0; 

编译运行:

  1. $ gcc -m32 -o main main.c 
  2. $ ./main 
  3. 2147483647 

可以看到,对于32位程序而言,long的最大值为2147483647。

溢出引发的问题

也就是说,一旦时间戳的值大于四字节的LONG_MAX,time_t将会无法正确存储这个时间戳。

举例来说,最开始的程序编译为32位程序,修改rawtime的值为2147483648,运行结果为(注意,溢出的结果是未定义的):

  1. #include <stdio.h> 
  2. #include <time.h> 
  3. int main (void)  
  4.    time_t rawtime = 2147483648;//time(NULL)获取当前时间戳 
  5.    struct tm info; 
  6.    //转为tm结构 
  7.    localtime_r( &rawtime,&info); 
  8.    //转为字符串 
  9.    printf("时间为: %s", asctime(&info)); 
  10.    return(0); 

然后我们编译运行:

  1. $ gcc -m32 -o main main.c 
  2. warning: this decimal constant is unsigned only in ISO C90 [enabled by default] 
  3. $ ./main 
  4. 间为: Sat Dec 14 04:45:52 1901 

首先编译的时候也有警告,原因在于2147483649无法使用time_t来表示,我们运行之后,也发现结果出乎我们的意料,它竟然是一个1901年的时间!

2038问题

那这和2038有什么关系呢?

编译为64位程序我们再次运行就会发现:

  1. 间为: Tue Jan 19 11:14:08 2038 

这个4字节整型表示的时间戳值只能表示到北京时间2038年1月19日11时14分07秒,一旦到了这时间之后,这些32位程序就可能运行异常,因为它们无法将此时间正确的识别为2038年,而可能会依个别实现而跳回1970年或1901年。

总结

到此,想必你已经很清楚了。由于在32位程序中,time_t最大值为2147483647,即最多表示到北京时间2038年1月19日11时14分07秒,因此在此之后就会出现异常。

而如果使用64位整型,则可以记录至约2900亿年后的292,277,026,596年12月4日15:30:08,星期日(UTC)。

当然,如果采用无符号整型,这个错误会被延后到 2106 年。到那时,还会有32位的程序在运行吗?

2038问题只是一个引子,实际上在程序中有很多现在不会溢出而将来可能溢出的问题,你会关注吗?

 

责任编辑:赵宁宁 来源: 编程珠玑
相关推荐

2020-10-22 14:27:39

Linux修复系统

2020-07-27 07:55:51

条件概率

2017-05-18 13:23:06

机器学习强化学习分类问题

2021-03-20 22:46:22

IaaSSaaSPaaS

2017-08-17 13:26:34

机器学习监督学习强化学习

2023-08-08 12:36:59

2023-09-01 13:49:00

内存进程线程

2020-07-14 14:59:00

控制反转依赖注入容器

2020-03-23 07:15:35

物联网IOT物联网技术

2018-03-13 11:34:11

物联网采购技术

2022-09-07 07:05:25

跨域问题安全架构

2015-01-23 10:17:23

DCIM数据中心运营与管理

2023-01-26 19:52:30

2019-12-23 11:03:07

抽象MOVJava

2017-12-19 21:29:58

物联网区块链大数据

2021-02-08 21:07:47

JavaCAS机制

2021-02-02 18:02:09

java对象数据

2020-11-20 10:51:03

云计算

2023-05-31 07:32:37

2023-02-15 07:03:41

跨域问题面试安全
点赞
收藏

51CTO技术栈公众号