I was playing with the time.h
file in C that helps us with time/day functions.
I came across:
struct tm * _Cdecl localtime(const time_t
The man page says:
The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions.
Also:
The localtime_r() function does the same, but stores the data in a user-supplied struct. It need not set tzname, timezone, and daylight.
It returns a pointer to a piece of statically allocated memory (probably either a static
variable defined inside localtime
or a global defined somewhere in the C runtime library). You must not free such memory.
Obviously this function is not reentrant (but can be thread-safe if TLS is used).
You must be careful when using this pointer: never make any function calls that could call localtime
/gmtime
/... before you finished using that pointer, otherwise the content of the memory referenced by your pointer could change (in response to the new call to localtime
) and you will be reading values relative to another time_t
.
In general the design of the date/time library is quite outdated, this kind of optimization was worthwhile when the C language was designed, nowadays it only gives problems.
To address these problems there are at least two different improved versions of these functions: localtime_r
(SUSv2, r
stays for "reentrant") and localtime_s
(Microsoft, s
stays for "safe"). The sad fact for portability is that these do almost the same thing (they require the destination struct tm
to be passed as a parameter), but differ in name and ordering of the parameters.
Actually localtime
usually returns the address of a static object. I suspect it looks like this:
struct tm *
localtime(const time_t *timer)
{
static struct tm tm;
/* Magic. */
return &tm;
}
The pointer returned by localtime
(and some other functions) are actually pointers to statically allocated memory. So you do not need to freed. Furthermore, you should not free it.
http://www.cplusplus.com/reference/clibrary/ctime/localtime/
This structure is statically allocated and shared by the functions gmtime and localtime. Each time either one of these functions is called the content of this structure is overwritten.
EDIT : Appending a few things mentioned in the comments.
A direct result of this shared data-structure is that localtime
and similar functions are not thread-safe. The thread-safe solution varies with different platforms. localtime_r for POSIX and localtime_s for MSVC.
They return a pointer to a static struct local to the library. From the man page:
NOTES The four functions asctime(), ctime(), gmtime() and localtime() return a pointer to static data and hence are not thread-safe. Thread-safe versions asctime_r(), ctime_r(), gmtime_r() and localtime_r() are spec‐ ified by SUSv2, and available since libc 5.2.5. POSIX.1-2001 says: "The asctime(), ctime(), gmtime(), and localtime() functions shall return values in one of two static objects: a broken- down time structure and an array of type char. Execution of any of the functions may overwrite the information returned in either of these objects by any of the other functions." This can occur in the glibc implementation.
The pointed object that is returned by localtime
function has static storage duration.