localtime返回的tm*指针对应内存是堆分配还是栈分配?
localtime函数的内存分配相关说明 直接给结论:符合C语言标准的localtime实现,绝对不会把返回的struct tm结构体存在自身函数的栈内存上,至于会不会做堆分配,标准没做强制要求,要看具体的C库实现:
- 首先说为什么不可能是栈分配:如果
localtime把结构体定义成自己函数内的局部栈变量,函数返回时对应的栈帧就会被回收,返回的指针直接变成悬空指针,访问就是未定义行为,所有正经实现都不会犯这种低级错误。 - 目前绝大多数主流C库(比如glibc、Windows自带的MSVC CRT)的实现,都是把返回的
struct tm存在静态存储区的全局静态变量里:这块内存是程序启动时就初始化好的,既不属于栈也不属于堆,用户不需要手动释放。但要注意两个常见的坑:- 这个实现不是线程安全的,多线程同时调用
localtime会出现数据竞争 - 多次调用
localtime会覆盖同一块内存的内容,不要长期持有返回的指针,举个典型错误写法:
time_t ts1 = 1690000000, ts2 = 1700000000; struct tm *t1 = localtime(&ts1); struct tm *t2 = localtime(&ts2); // 此时t1和t2指向同一块静态内存,内容全是ts2转换后的结果,t1原本存的ts1的时间已经被覆盖了 - 这个实现不是线程安全的,多线程同时调用
- 少部分特殊实现(比如部分嵌入式C库、定制化的线程安全改造版本)确实可能用堆内存存储返回的结构体,但这类实现都会在库内部做统一的内存管理,绝对不会要求用户手动释放返回的指针——不然接口本身就违反了通用使用约定,很容易造成内存泄漏或者重复释放的问题。
- 最后给个使用提醒:不管你用的C库是哪种实现,都不要尝试
freelocaltime返回的指针,这块内存的生命周期完全由C库本身管理,用户不需要做额外处理。如果需要线程安全、或者要长期保存转换后的时间结果,优先用标准定义的可重入版本localtime_r,自己提前定义好struct tm变量把地址传进去就行,完全不用操心内存分配的问题。
内容的提问来源于stack exchange,提问作者triangleboi
相关产品推荐
相关产品推荐

