时间函数 localtime localtime_r

时间函数 localtime localtime_r

localtime 和 localtime_r 的函数功能: converts the calendar time timep to broken-time representation

在调用 localtime 和 localtime_t 函数时,需特别注意:

localtime 是不可重入函数,非线程安全

localtime_r 是可重入函数,线程安全

使用 localtime 时不可重入示范:

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <time.h>

int main()

{

time_t curTime = time(NULL);

time_t aftTime = curTime + 3600*3;

struct tm *pTm1 = localtime(&curTime);

struct tm *pTm2 = localtime(&aftTime);

fprintf(stdout, "%04d%02d%02d%02d%02d%02d\n",

pTm1->tm_year + 1900,

pTm1->tm_mon + 1,

pTm1->tm_mday,

pTm1->tm_hour,

pTm1->tm_min,

pTm1->tm_sec);

fprintf(stdout, "%04d%02d%02d%02d%02d%02d\n",

pTm2->tm_year + 1900,

pTm2->tm_mon + 1,

pTm2->tm_mday,

pTm2->tm_hour,

pTm2->tm_min,

pTm2->tm_sec);

return 0;

}

编译 & 运行:

$ gcc -o main main.c

$ ./main

20180704225205

20180704225205

调用 localtime 函数并获取其返回值(一个指向 struct tm 结构类型数据的指针)后,我们并未对返回值进行显式地释放。

这并没有什么问题(不会导致内存泄漏)。

因为 localtime 函数返回值是一个指针,指向一个静态变量,这个静态变量是库中的一个 static struct tm 类型数据。

man localtime:

The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions.

这将引出新的问题,同一进程多个线程中同时调用(极短时间内连续调用) localtime 函数,返回值(tm)可能被覆盖。

举个栗子:

两个线程A和B同时调用 localtime 函数:

时刻1:线程A调用 localtime 函数,得到一个指针,指向 static struct tm 类型变量;(tm中存储的值更新为 value-a)

时刻2:线程B调用 localtime 函数,得到一个指针,指向 static struct tm 类型变量;(tm中存储的值更新为 value-b)

时刻3:线程A对 localtime 返回的指针进行相关引用操作(例如 printf 输出某字段),此时 static struct tm 中的值实际是 value-b,并非预期的 value-a

时刻4:线程B对 localtime 返回的指针进行相关引用操作,此时 static struct tm 中的值实际是 value-b

上面的示范代码虽然是在同一线程中,但是已经可以简单模拟这样的多线程执行调用流程。

如何解决?

localtime_r 是 localtime 的可重入版本(线程安全版本)。

localtime 不可重入是由于 static struct tm 是库中的一个静态变量,如果我们在调用 localtime 时传入一个 struct tm 类型变量(指针)用于存放结果,岂不是实现可重入?

Bingo!

struct tm *localtime(const time_t *timep);

struct tm *localtime_r(const time_t *timep, struct tm *result);

调用 localtime 只需要传入指向 time_t 的一个常量指针;

调用 localtime_t 不仅需要传入指向 time_t 的一个常量指针,还需要传入指向 struct tm 的一个指针,结果将存储在 result 指向的 struct tm 对象中;

The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions.

The localtime_r() function does the same, but stores the data in a user-supplied struct.

使用 localtime_r 时可重入示范:

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <time.h>

int main()

{

time_t curTime = time(NULL);

time_t aftTime = curTime + 3600*3;

struct tm tm1;

struct tm tm2;

localtime_r(&curTime, &tm1);

localtime_r(&aftTime, &tm2);

fprintf(stdout, "%04d%02d%02d%02d%02d%02d\n",

tm1.tm_year + 1900,

tm1.tm_mon + 1,

tm1.tm_mday,

tm1.tm_hour,

tm1.tm_min,

tm1.tm_sec);

fprintf(stdout, "%04d%02d%02d%02d%02d%02d\n",

tm2.tm_year + 1900,

tm2.tm_mon + 1,

tm2.tm_mday,

tm2.tm_hour,

tm2.tm_min,

tm2.tm_sec);

return 0;

}

编译 & 运行:

$ gcc -o main main.c

$ ./main

20180704200531

20180704230531

相关推荐
从零开始学习人工智能1 小时前
从Token到序列:阿里GSPO算法如何让大模型训练更稳、更强?
人工智能·算法·机器学习
用户6120414922131 小时前
C语言做的贪食蛇游戏(控制台版)
c语言·后端·游戏开发
好易学·数据结构4 小时前
可视化图解算法57:字符串的排列
数据结构·算法·leetcode·面试·笔试·回溯算法·牛客
এ᭄画画的北北7 小时前
力扣-283.移动零
算法·leetcode
2501_924879369 小时前
口罩识别场景误报率↓79%:陌讯多模态融合算法实战解析
人工智能·深度学习·算法·目标检测·智慧城市
Christo310 小时前
TFS-2022《A Novel Data-Driven Approach to Autonomous Fuzzy Clustering》
人工智能·算法·机器学习·支持向量机·tfs
木木子999910 小时前
超平面(Hyperplane)是什么?
算法·机器学习·支持向量机·超平面·hyperplane
sakabu10 小时前
cJSON库应用
c语言·笔记·学习
星空下的曙光11 小时前
React 虚拟 DOM Diff 算法详解,Vue、Snabbdom 与 React 算法对比
vue.js·算法·react.js
♞沉寂11 小时前
数据结构——双向链表
数据结构·算法·链表