Linux下stat与tm结构体获取文件时间时time1变量异常问题
我看你在Linux下用Eclipse搭配g++开发,要实现获取文件时间并输出月份、小时这类信息的功能,但调试时碰到了time1变量值莫名变更的问题。结合你给出的代码片段,这几乎肯定是C标准库时间函数的一个经典坑!
问题根源分析
你定义的struct tm *time1, *time2;是指针类型,而我们常用的localtime()、gmtime()这类函数,返回的是指向静态内存缓冲区的指针。也就是说,系统只会分配一块固定的内存来存储解析后的时间结构体,每次调用这些函数,都会把新的时间数据覆盖到这块内存里。
举个例子:如果你的filetime1()函数里执行了time1 = localtime(&stat1.st_mtime);,之后filetime2()里又调用time2 = localtime(&stat2.st_mtime);,那么time1和time2实际上指向的是同一块内存!后面的调用会直接覆盖前面的时间数据,导致你再访问time1时,看到的已经是stat2对应的时间了,这就是你觉得time1值意外变更的原因。
两种可行的解决方案
1. 改用线程安全的localtime_r()(推荐)
Linux系统提供了localtime_r()函数,它需要你提前分配好自己的struct tm内存空间,把指针传入函数,结果会直接写到你指定的缓冲区里,完全避免了静态缓冲区覆盖的问题。调整后的代码示例:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <time.h> // 定义实际的结构体变量,而不是指针 struct stat stat1, stat2; struct tm time1_buf, time2_buf; void filestat1(void) { // 这里实现stat1的获取逻辑,比如stat("file1", &stat1) } void filestat2(void) { // 这里实现stat2的获取逻辑,比如stat("file2", &stat2) } void filetime1(void) { // 使用localtime_r把时间解析到自己的缓冲区 localtime_r(&stat1.st_mtime, &time1_buf); // 之后直接访问time1_buf的成员,比如time1_buf.tm_mon(注意月份是0-11)、time1_buf.tm_hour } void filetime2(void) { localtime_r(&stat2.st_mtime, &time2_buf); // 访问time2_buf的成员即可 }
2. 手动复制结构体内容(兼容旧代码场景)
如果因为某些原因必须使用localtime(),那拿到指针后要立刻把结构体内容复制到自己的变量里,避免后续调用覆盖:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <time.h> struct stat stat1, stat2; // 定义实际的结构体变量,不是指针 struct tm time1, time2; void filetime1(void) { struct tm *tmp_ptr = localtime(&stat1.st_mtime); if (tmp_ptr != NULL) { // 把静态缓冲区的内容复制到自己的变量 time1 = *tmp_ptr; } } void filetime2(void) { struct tm *tmp_ptr = localtime(&stat2.st_mtime); if (tmp_ptr != NULL) { time2 = *tmp_ptr; } }
额外调试小技巧
调试的时候可以查看time1和time2的内存地址,如果两者地址完全相同,就坐实了是静态缓冲区覆盖的问题。另外,别忘了检查stat()函数的返回值,确保stat1和stat2确实正确获取到了文件的状态信息,避免因为文件不存在、权限不足等问题导致后续时间处理出错。
内容的提问来源于stack exchange,提问作者Aiden

