c - 当传递值 >0x7FFFFFFF 时 localtime() 崩溃
问题描述
根据我的理解 time_t rawtime = 0xffFFffFF
是GMT: 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:我需要有一系列警报并在时机成熟时采取行动。这是嵌入式系统,我无法为复杂的数据类型提供内存和资源。
解决方案
在大多数平台上,类型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。
推荐阅读
- google-cloud-platform - GCP Python SDK - 在没有 gcloud 的情况下启用 API
- php - 获取数据后如何选择下拉列表
- reactjs - 顺风CSS渐变问题
- linux - Bash:使用 bash 脚本抓取文本文件以查找电话号码
- javascript - 如何自动调用类中的函数
- ios - Getting an image-related exception when using a ListWheelScrollView in Flutter
- android - Android Kotlin - 在工具栏内设置徽标
- postgresql - 针对真实 postgres 数据库的 Spring Boot 集成测试
- swift - 存在方式通知何时将呈现自定义 UIView 或 removeFromSuperview()?
- dialogflow-cx - 使用 EventHandler 警告用户他们的会话即将结束