C - 当传递值>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("%sn", 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表示错误。因此,尽管我从未遇到过它,但如果有localtime()实现将输入的值-1视为错误,我并不完全感到惊讶。

你说它"崩溃了",但那有一部分是你的错。localtime通过返回空指针表示失败。所以写

更安全
struct tm *ts;
ts = localtime(&rawtime);
if(ts == NULL) {
fprintf(stderr, "localtime failedn");
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日算起,甚至不需要是个整数。即使这些事实成立,也没有规则说time_t必须签名,所以在一个为广泛可移植性而设计的程序中,我不会指望有对应于1901-1970的值,因为在某些平台上它们可能对应于2038-2106,毕竟。

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

如果你正在使用的编译器没有一个time_t的范围满足你的要求,你可以:

  • 使用不同的编译器,或者
  • 避免使用time_t
  • 重新构建你的程序,使其在编译器的time_t限制内工作。

正如在注释中提到的,很可能是由于localtime由于超出范围的输入而返回空指针,并且您在没有首先检查null的情况下解引用它。

相关内容

  • 没有找到相关文章

最新更新