struct tm指针使用不稳定问题排查及优化方案咨询
malloc分配struct tm导致mktime结果不稳定的原因及优化方案
本人英文水平有限,还请见谅。
[代码1] 有时结果为-0(错误),有时为62726400(正确)。
[代码2] 结果始终为62726400(正确)。
请问代码1为何不稳定?如何优化代码1?
代码1
// Code 1 time_t timer2; struct tm *t2 = (struct tm*)malloc(sizeof(struct tm)); t2->tm_year = 1997 - 1900; t2->tm_mon = 9 - 1; t2->tm_mday = 14; timer2 = mktime(t2); time_t timer3; struct tm *t3 = (struct tm*)malloc(sizeof(struct tm)); t3->tm_year = 1995 - 1900; t3->tm_mon = 9 - 1; t3->tm_mday = 19; timer3 = mktime(t3); double diffA = difftime(timer2, timer3); printf("%.f\n", diffA);
代码2
// Code 2 printf("When struct tm is not pointer\n"); time_t timer4; struct tm t4 = {0}; t4.tm_year = 1997 - 1900; t4.tm_mon = 9 - 1; t4.tm_mday = 14; timer4 = mktime(&t4); time_t timer5; struct tm t5 = {0}; t5.tm_year = 1995 - 1900; t5.tm_mon = 9 - 1; t5.tm_mday = 19; timer5 = mktime(&t5); double diffB = difftime(timer4, timer5); printf("%.f", diffB);
我尝试了两种内存分配方式:struct tm *t2 = (struct tm*)malloc(sizeof(struct tm));
和struct tm *t2 = malloc(sizeof(*t2));
但两种方式的结果均不稳定。
原因分析
malloc分配的内存是未初始化的脏内存,struct tm里除了你手动设置的tm_year、tm_mon、tm_mday,其他字段(比如tm_hour、tm_min、tm_sec、tm_isdst等)都是随机的垃圾值。mktime函数需要依赖完整的struct tm字段进行时间转换,尤其是tm_isdst(夏令时标记),如果它是随机的无效值,会导致mktime转换失败,返回-1。此时difftime计算两个-1的差值就是0,打印时就会显示-0。- 代码2中用
struct tm t4 = {0};初始化了整个结构体,所有未显式设置的字段都被置为0,mktime能正确解析时间,所以结果始终稳定。
优化方案
方案1:初始化malloc分配的内存
用memset把结构体所有字段置0,再设置需要的时间值:
struct tm *t2 = malloc(sizeof(struct tm)); memset(t2, 0, sizeof(struct tm)); // 初始化全部字段为0 t2->tm_year = 1997 - 1900; t2->tm_mon = 9 - 1; t2->tm_mday = 14; timer2 = mktime(t2);
也可以直接用calloc代替malloc,calloc会自动将分配的内存初始化为0:
struct tm *t2 = calloc(1, sizeof(struct tm)); // 等价于malloc+memset t2->tm_year = 1997 - 1900; t2->tm_mon = 9 - 1; t2->tm_mday = 14; timer2 = mktime(t2);
方案2:显式设置所有关键字段
如果你不想初始化全部字段,可以手动设置mktime依赖的关键字段,比如:
struct tm *t2 = malloc(sizeof(struct tm)); t2->tm_year = 1997 - 1900; t2->tm_mon = 9 - 1; t2->tm_mday = 14; t2->tm_hour = 0; t2->tm_min = 0; t2->tm_sec = 0; t2->tm_isdst = -1; // 让系统自动判断是否为夏令时 timer2 = mktime(t2);
不过这种方式需要确保没有遗漏关键字段,不如直接初始化整个结构体稳妥。
内容的提问来源于stack exchange,提问作者游琇雯
相关产品推荐
相关产品推荐

