<time.h> 共享内部对象 - struct tm

<time.h> Shared Internal Object - struct tm

我正在研究 C 时间库的例程,因为我需要一种方法来跟踪程序日志文件中的时间。我发现这样做的方法是拥有一个 time_t 对象,它只包含自 1970 年 1 月 1 日以来的秒数 00:00 UTC。然后,我将此 time_t 对象解析为 localtime(time_t* argument) 例程,这将 return 指向 tm 结构的指针。自 1970 年 1 月 1 日以来,后者将以更复杂的结构保存时间,以秒为单位将时间转换为年、月、日、小时等。这个 tm 结构指针最终可以被 asctime(strcut tm* argument) 至 return 日志的人类友好时间(即 2016 年 9 月 7 日星期三 13:45:23)。

我的问题是关于 struct tm 对象的。正如我们在 Cplusplus 的示例代码中所见,struct tm 对象从未被声明,只是一个指针。这意味着这个对象在其他地方声明,我们只是访问它。参考 link 本身指出:

"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时库吗?这是否意味着加载库的第一个进程将声明该对象,而所有其他进程将仅与已声明的对象共享该库?为了避免那些数据竞争问题,为每个调用创建一个新的 struct tm 对象和 return 一个指向它的指针以便每个程序都有自己的结构不是更好吗?

也许每个使用 Ctime 的程序都有一个 struct tm MyProgramStruct; localtime(&Rawtime, &MyProgramStruct); 而不是一个结构?有什么理由改用这种方式吗?

最后,使用 C 时间库 localtime 例程是否是一种不好的做法,因为程序不同步可能导致错误输出?

来自 link 的示例代码:

/* 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;
}

So, who creates the struct tm object? Is it the C time library in the first time it is loaded?

根据 localtime() 函数的文档,它 returns 一个指向 静态分配的 结构的指针。该结构属于 C 库;该函数提供了一个指向它的指针。它所在的确切位置以及确切的存储分配时间和方式等细节并不重要,并且可能因实施而异。您只需要了解同一进程的不同调用会处理并提供指向同一结构的指针。

That would mean that the first process that loads the library would declare the object and all other processes would just share this library with the object already declared?

没有。您无需担心结构在进程之间共享,只需担心它在多个调用之间以及同一进程中的多个线程之间共享。

Wouldn't it be better, in order to avoid those Data Races issues, to just create a new struct tm object for each call and return a pointer to it so each program has its own structure? Maybe having a struct tm MyProgramStruct; localtime(&Rawtime, &MyProgramStruct); instead of a single struct for every program using Ctime? Any reason it's done this way instead?

再说一遍,不是跨进程的问题,只是进程内的问题,还是够糟的。是的,这个问题可以通过不共享结构来解决,这就是函数 localtime_r() 的区别所在,它是可用的。但是不能更改现有功能来执行相同的操作,因为这会给用户带来新的要求以释放所提供的结构。

localtime() 的设计者想让它易于使用,而且确实如此,只要您不 运行 违反共享数据问题。如果你的程序是单线程的,那么你可以很容易地避免它。 localtime() 不是唯一存在此类问题的标准库函数。

Finally, is using C time library localtime routine a bad practice because of the possibility of the unsynchronization of programs leading to a wrong output?

不是那个原因,不是,因为没有跨进程的问题。你在使用localtime()等类似静态存储的函数时需要注意,比如strtok()。但是你可以逐个程序来判断是否存在数据竞争——你不需要担心不明其他程序的干扰。