55
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );

This returns: warning C4996: 'localtime': This function or variable may be unsafe. Consider using localtime_s instead.

time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime_s ( &rawtime );

When I change localtime to localtime_s I get: error C2660: 'localtime_s' : function does not take 1 arguments

Here is what I think is going on in the first block of code:

  • create an empty time_t variable.
  • create a pointer to timeinfo which is defined in ctime
  • write the rawtime into a rawtime reference
  • convert the rawtime into something meaningful to pedestrians

    1. Am I right?
    2. What second input parameter does localtime_s need?
    3. What's the worst that could happen if I just ignore the whole localtime safety issue.
ProGirlXOXO
  • 2,170
  • 6
  • 25
  • 47
  • 1
    yes, I found this immediately: http://msdn.microsoft.com/en-us/library/a442x3ye(v=vs.80).aspx but I don't yet understand how to interpret these template/generic? descriptions of methods. Much like I don't understand the syntax/symbols of general form wiki math articles. struct tm* _tm and const time_t *time doesn't mean anything to me as far as what I'm really telling the method... though I wish it did. – ProGirlXOXO Jan 17 '13 at 21:21
  • Yes, I have some of those too. – ProGirlXOXO Jan 17 '13 at 21:42

3 Answers3

69

localtime returns a pointer to a statically allocated struct tm.

With localtime_s, you pass in a pointer to a struct tm, and localtime_s writes its result data into that, so your code would change from:

struct tm *timeinfo;
timeinfo = localtime(&rawtime);

to something like:

struct tm timeinfo;
localtime_s(&timeinfo, &rawtime);

This way, it's writing to your buffer instead of having a buffer of its own.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • With those changes I get these errors: error C2679: binary '=' : no operator found which takes a right-hand operand of type 'errno_t' (or there is no acceptable conversion) 1> c:\Program Files\Microsoft Visual Studio 10.0\VC\include\wchar.h(1120): could be 'tm &tm::operator =(const tm &)' 1> while trying to match the argument list '(tm, errno_t)' error C2664: 'strftime' : cannot convert parameter 4 from 'tm' to 'const tm *' 1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called – ProGirlXOXO Jan 17 '13 at 21:03
  • 1
    @ProGirlXOXO: That's clearly happening in code you haven't shown above, but it's probably because `timeinfo` is now a `struct tm` instead of a pointer, so where other functions use it, you'll need to change `timeinfo` to `&timeinfo`. – Jerry Coffin Jan 17 '13 at 21:40
  • This line: &timeinfo = localtime_s ( &timeinfo, &rawtime ); Gives this error: error C2440: '=' : cannot convert from 'errno_t' to 'tm *' – ProGirlXOXO Jan 18 '13 at 00:21
  • 5
    @ProGirlXOXO: Reread the answer. `localtime` returns a pointer to a `struct tm` -- `localtime_s` does *not* (it returns an error number to tell you whether the conversion you requested succeeded or not). – Jerry Coffin Jan 18 '13 at 00:23
8

localtime_s is just a microsoft implementation of the localtime functon, you can safely keep using locatime becaue it's C++ ISO compliant and ony microsoft marked it as "deprecated". The localtime function itself isn't deprecated at all in the C++ world.

The localtime_s reference says that these parameters should be passed to it:

_tm 
Pointer to the time structure to be filled in.
 time 
Pointer to the stored time.
  • 12
    FWIW, the POSIX standard corrected function is `localtime_r`. Works exactly the same, except the order of the two arguments is reversed. – Ben Voigt Dec 29 '14 at 14:49
  • `localtime_s` is part of the [standard](https://en.cppreference.com/w/c/chrono/localtime) since C11. – Pietro May 14 '19 at 09:57
  • 1
    @Pietro Only as part of the [optional Annex K](https://port70.net/~nsz/c/c11/n1570.html#K), which has *de facto* only been (poorly) implemented by Microsoft. Per [**Field Experience With Annex K — Bounds Checking Interfaces**](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm#impementations): "As a result of the numerous deviations from the specification the Microsoft implementation cannot be considered conforming or portable." – Andrew Henle Jul 13 '20 at 13:45
  • @AndrewHenle - Thank you for pointing this out. Just read on cppreference: "The implementation of localtime_s in Microsoft CRT is incompatible with the C standard since it has reversed parameter order." – Pietro Jul 16 '20 at 16:38
7

As Lightness Races in Orbit pointed out, localtime is not thread safe as well as several other time function. I wanted to know more about the subject and I found a relevant blog post with a thoughrough explanation about that.

The quote below explains why localtimeis not thread-safe:

[...] localtime returns a pointer to a static buffer (std::tm*). Another thread can call the function and the static buffer could be overwritten before the first thread has finished reading the content of the struct std::tm*.

Community
  • 1
  • 1
ForceMagic
  • 6,230
  • 12
  • 66
  • 88