c++cvisual-c++timelocaltime

Does localtime return a heap allocated tm*


As you know the <time.h> standard header defines the struct tm and a function called localtime.

Does localtime make a heap allocation?
Or is it allocated in the stack?
It returns a pointer but this could be just a pointer to the stack value, right?


Solution

  • The relevant part of the C Standard (C18) has this language:

    7.27.3 Time conversion functions

    Except for the strftime function, these functions each return a pointer to one of two types of static objects: a broken-down time structure or an array of char. Execution of any of the functions that return a pointer to one of these object types may overwrite the information in any object of the same type pointed to by the value returned from any previous call to any of them and the functions are not required to avoid data races with each other. The implementation shall behave as if no other library functions call these functions.

    localtime returns a pointer to a static struct tm object, ie: a global object that may or may not be thread local. The contents of this object can be overwritten by a subsequent call to this or another library function. It should not be accessed after the thread in which it the function was called has exited.

    The object is not allocated from the heap, You must not call free with this pointer.

    The object cannot be allocated with automatic storage as accessing it after the function localtime returns would have undefined behavior.

    Instead of localtime, you should use localtime_r, a POSIX function that will be included in the next version of the C Standard (C23):

    #include <time.h>
    struct tm *localtime_r(const time_t *timer, struct tm *buf);
    

    localtime_r takes a pointer to the destination object, which you can define or allocate as appropriate for your usage.

    MSVC might not support this function, but you can define it on its target platforms as a simple macro:

    #ifdef _MSC_VER
    #define localtime_r(a,b)  localtime_s(a,b)
    #endif