You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言Unix时间戳转换异常:gmtime调用致旧指针失效

C语言gmtime调用引发的时间输出异常问题

当注释掉代码中标记的3行时,程序输出正常:

1st Printing of Timestamp (UTC): 08/19/2023 15:04:48  (Unix Epoch time: 1692457488)
2nd Printing of Timestamp (UTC): 08/19/2023 15:04:48  (Unix Epoch time: 1692457488)

取消这3行注释后,第二次输出的时间变成了当前系统UTC时间,但Unix时间戳仍正确:

1st Printing of Timestamp (UTC): 08/19/2023 15:04:48  (Unix Epoch time: 1692457488)
2nd Printing of Timestamp (UTC): 08/19/2023 20:27:57  (Unix Epoch time: 1692457488)

问题代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>


int main()
{
    // Get a Unix epoch value
    long long timestamp_ms = 1692457488113;
    char formatted_time[50]; // only need 20 characters to hold "MM/DD/YYYY HH:MM:SS"

    // Convert Unix timestamp to "MM/DD/YYYY HH:MM:SS" format in UTC time
    time_t timestamp_seconds = (time_t)(timestamp_ms / 1000); // Convert milliseconds to seconds
    struct tm *timestamp_timeinfo = gmtime(&timestamp_seconds); // Use gmtime for UTC time

    // print result - should be 08/19/2023 15:04:48  (Unix Epoch time: 1692457488)
    strftime(formatted_time, sizeof(formatted_time), "%m/%d/%Y %H:%M:%S", timestamp_timeinfo);
    printf("1st Printing of Timestamp (UTC): %s  (Unix Epoch time: %lld)\n", formatted_time, timestamp_ms/1000);

       
/*    time_t current_utc_time; // Get current UTC time  grabbing variabluse I do nothing with (suspect gmtime memory leak)
      time(&current_utc_time);
      struct tm *current_timeinfo = gmtime(&current_utc_time);  
*/


    // print again, should be "08/19/2023 15:04:48  (Unix Epoch time: 1692457488)" but it is not
    strftime(formatted_time, sizeof(formatted_time), "%m/%d/%Y %H:%M:%S", timestamp_timeinfo);
    printf("2nd Printing of Timestamp (UTC): %s  (Unix Epoch time: %lld)\n", formatted_time, timestamp_ms/1000);

    return 0;
} 

问题根源

gmtime函数返回的指针指向静态分配的全局缓冲区,所有对gmtime的调用都会复用这块内存。第一次调用gmtime时,缓冲区被填充为目标时间的struct tm数据;当取消注释后,第二次调用gmtime(&current_utc_time)会覆盖这个缓冲区的内容,把它改成当前UTC时间。而你保存的timestamp_timeinfo指针依然指向这块被覆盖的缓冲区,所以第二次调用strftime时,读取的是被覆盖后的当前时间数据,导致输出异常。

解决方案

有两种可靠的修复方式:

1. 使用线程安全的gmtime_r(POSIX标准)

gmtime_r要求你自己提供struct tm缓冲区,避免依赖全局静态内存,从根本上杜绝覆盖问题:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    long long timestamp_ms = 1692457488113;
    char formatted_time[50];

    time_t timestamp_seconds = (time_t)(timestamp_ms / 1000);
    struct tm timestamp_timeinfo; // 自己定义结构体变量
    gmtime_r(&timestamp_seconds, &timestamp_timeinfo); // 写入自己的缓冲区

    strftime(formatted_time, sizeof(formatted_time), "%m/%d/%Y %H:%M:%S", &timestamp_timeinfo);
    printf("1st Printing of Timestamp (UTC): %s  (Unix Epoch time: %lld)\n", formatted_time, timestamp_ms/1000);

    // 取消注释这部分也不会影响结果
    time_t current_utc_time;
    time(&current_utc_time);
    struct tm current_timeinfo;
    gmtime_r(&current_utc_time, &current_timeinfo);

    strftime(formatted_time, sizeof(formatted_time), "%m/%d/%Y %H:%M:%S", &timestamp_timeinfo);
    printf("2nd Printing of Timestamp (UTC): %s  (Unix Epoch time: %lld)\n", formatted_time, timestamp_ms/1000);

    return 0;
}

2. 复制struct tm内容到本地变量

如果你的环境不支持gmtime_r,可以在第一次调用gmtime后,将返回的结构体内容复制到自己定义的变量中:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h> // 用于memcpy

int main()
{
    long long timestamp_ms = 1692457488113;
    char formatted_time[50];

    time_t timestamp_seconds = (time_t)(timestamp_ms / 1000);
    struct tm *temp_info = gmtime(&timestamp_seconds);
    struct tm timestamp_timeinfo;
    memcpy(&timestamp_timeinfo, temp_info, sizeof(struct tm)); // 复制静态缓冲区的内容

    strftime(formatted_time, sizeof(formatted_time), "%m/%d/%Y %H:%M:%S", &timestamp_timeinfo);
    printf("1st Printing of Timestamp (UTC): %s  (Unix Epoch time: %lld)\n", formatted_time, timestamp_ms/1000);

    // 取消注释这部分也不会影响结果
    time_t current_utc_time;
    time(&current_utc_time);
    struct tm *current_timeinfo = gmtime(&current_utc_time);

    strftime(formatted_time, sizeof(formatted_time), "%m/%d/%Y %H:%M:%S", &timestamp_timeinfo);
    printf("2nd Printing of Timestamp (UTC): %s  (Unix Epoch time: %lld)\n", formatted_time, timestamp_ms/1000);

    return 0;
}

内容的提问来源于stack exchange,提问作者relayman357

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 16:25:41