[英]<time.h> Shared Internal Object - struct tm
我一直在研究C时间库的例程,因为我需要一种跟踪程序日志文件中时间的方法。 我发现执行此操作的方法是拥有一个time_t
对象,该对象仅保留自1970年1月1日UTC 00:00以来的秒数。 然后,我将此time_t
对象解析为localtime(time_t* argument)
例程,该例程将返回指向tm
结构的指针。 从1970年1月1日开始,后者将以更复杂的结构保存时间,将以秒为单位的时间转换为年,月,日,小时等。从1970年1月1日开始,此tm
结构指针最终可以由asctime(strcut tm* argument)
返回人类友好的日志记录时间(即2016年9月7日星期三13:45:23)。
我的问题是关于struct tm
对象。 正如我们在Cplusplus的示例代码中看到的那样,从不声明struct tm
对象,而仅声明了一个指针。 意味着此对象在其他地方声明,我们正在访问它。 参考链接本身指出:
"The function also accesses and modifies a shared internal object,
which may introduce data races on concurrent calls to gmtime and
localtime. Some libraries provide an alternative function that avoids
this data race: localtime_r (non-portable)."
那么,谁创建了struct tm
对象? 第一次加载时是C时间库吗? 那是否意味着加载该库的第一个进程将声明该对象,而所有其他进程将仅与已声明的对象共享该库? 为了避免这些Data Races问题,只为每个调用创建一个新的struct tm
对象并返回一个指向它的指针,以便每个程序都有自己的结构,这会更好吗?
也许有一个struct tm MyProgramStruct; localtime(&Rawtime, &MyProgramStruct);
struct tm MyProgramStruct; localtime(&Rawtime, &MyProgramStruct);
而不是每个使用Ctime的程序都使用单个结构? 这样做有任何原因吗?
最后,由于可能由于程序不同步而导致错误输出,因此使用C时间库localtime
时间例程是否是一种不好的做法?
链接中的示例代码:
/* localtime example */
#include <stdio.h> /* puts, printf */
#include <time.h> /* time_t, struct tm, time, localtime */
int main ()
{
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime (&rawtime);
printf ("Current local time and date: %s", asctime(timeinfo));
return 0;
}
那么,谁创建了struct tm对象? 第一次加载时是C时间库吗?
根据localtime()
函数的文档,它返回一个指向静态分配的结构的指针。 该结构属于C库; 该函数提供了指向它的指针。 确切的位置以及确切的存储时间和分配方式的详细信息无关紧要,并且可能因实现而异。 您只需要了解同一进程的不同调用可以一起使用并提供指向同一结构的指针。
那是否意味着加载该库的第一个进程将声明该对象,而所有其他进程将仅与已声明的对象共享该库?
不需要。您不必担心结构在进程之间共享,而只需要担心跨多个调用以及同一进程中的多个线程之间共享该结构。
为了避免这些Data Races问题,只为每个调用创建一个新的struct tm对象并返回一个指向它的指针,以便每个程序都有自己的结构,这会更好吗? 也许有一个
struct tm MyProgramStruct; localtime(&Rawtime, &MyProgramStruct);
struct tm MyProgramStruct; localtime(&Rawtime, &MyProgramStruct);
而不是每个使用Ctime的程序都使用单个结构? 这样做有任何原因吗?
同样,这不是跨进程问题,而只是一个进程内问题,这仍然很糟糕。 是的,可以通过不共享该结构来解决该问题,这就是区分函数localtime_r()
地方。 但是现有功能不能更改为相同功能,因为这将对用户释放新提供的结构提出新要求。
localtime()
的设计者希望使其易于使用,的确如此,只要您不担心共享数据问题。 如果您的程序是单线程的,则可以很容易地避免使用它。 localtime()
并非唯一具有此类问题的标准库函数。
最后,由于可能由于程序不同步而导致错误输出,因此使用C时间库
localtime
时间例程是否是一种不好的做法?
不是因为这个原因,不是,因为没有跨进程问题。 在使用localtime()
和其他具有类似静态存储的函数时,您确实需要注意,例如strtok()
。 但是您可以根据程序逐个判断是否存在任何数据争用-您无需担心未指定的其他程序的干扰。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.