0
time_t rawtime;
struct tm * timeinfo;

time(&rawtime);
timeinfo = localtime(&rawtime);

heure_= timeinfo->tm_hour;
minute_ = timeinfo->tm_min;
seconde_ = timeinfo->tm_sec;
jourMois_ = timeinfo->tm_mday;
jourSemaine_ = timeinfo->tm_wday;
mois_ = timeinfo->tm_mon;
annee_ = timeinfo->tm_year;

This is my implementation for a function that look up the time, the date,.... and so on.

I don`t know why but I get the error:

1>c:\users\sebastien\blabla: warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data

1> DateHeure.cpp

1>c:\users\sebastien\blabla-> error C4996: 'localtime': This function or variable may be unsafe. Consider using localtime_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

1> c:\program files (x86)\microsoft visual studio

12.0\vc\include\time.inl(112) : see declaration of 'localtime'

I have tried to change localtime to localtime_s but I get some error message concerning compatibility with parameter of type "tm".

I have also tried to (include or wright) __CRT_SECURE_NO_WARNINGS but with no success -> I don't know but just including this line seems odd (in the properties>c++>preprocessor>undefined preprocessor definitions) without adding anything else.

Acknowledge that I am not that familiar with Visual Studio, so I am not sure with all these properties setting and tweaking.

but I would really appreciate if one could help me with this time thing, I think it's my only error, I'll debug after to be sure.

Please include some information on the why... I'd like to understand.

Community
  • 1
  • 1
  • Is it C or C++? Add the language tag. – Yu Hao Mar 16 '15 at 02:09
  • @Yu Hao, can you tell me why you changed all the i to capital, even though they are not all starting a sentence ? (english is not my birth language, sorry for the mistakes) but is it ike something people do here ? (what are the reson) – Sebastien Comtois Mar 16 '15 at 02:17
  • 3
    [I](http://en.wikipedia.org/wiki/I#Use_in_English) is always written with a capital letter in English. – Yu Hao Mar 16 '15 at 02:34
  • Closely related: http://stackoverflow.com/q/14386923/103167 – Ben Voigt Mar 16 '15 at 03:10

2 Answers2

4

C4996 isn't supposed to be an error, I suppose you adjusted your compile options to make it one. (Or the project wizard did)

Anyway, the alternate functions that don't use static local buffers ARE better, and they're also portable (in everything except the name, it's localtime_s on Win32 and localtime_r on Linux, which a macro can fix), so there's really no reason not to use them.

The versions without static local buffer expect you to supply a buffer, which is easy:

time_t rawtime;
struct tm timeinfo;  // no longer a pointer

time(&rawtime);

// on platforms with POSIX localtime_r but no localtime_s, add this macro
// #define localtime_s(x, y) localtime_r(y, x)
localtime_s(&timeinfo, &rawtime); // fills in your structure,
                                  // instead of returning a pointer to a static one

heure_= timeinfo.tm_hour;  // no longer using a pointer
minute_ = timeinfo.tm_min;
seconde_ = timeinfo.tm_sec;
jourMois_ = timeinfo.tm_mday;
jourSemaine_ = timeinfo.tm_wday;
mois_ = timeinfo.tm_mon;
annee_ = timeinfo.tm_year;
Community
  • 1
  • 1
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • I will look on the difference between those, i just didnt find anything that said i had to use two argument instead of one (with localtime_s)...i need to look more into your code, but , thak you sir, really helpful. – Sebastien Comtois Mar 16 '15 at 03:22
  • 1
    When in doubt about how to call a function, you can always refer to the [documentation](https://msdn.microsoft.com/en-us/library/a442x3ye.aspx). Finding it is usually as simple as putting the cursor on the function name and pressing F1. – Retired Ninja Mar 16 '15 at 03:30
1

The localtime function can be unsafe as the pointer it returns points to a structure that is used for itself and other calls. That means if you call a function that changes that internal structure all the pointers that point to it would reflect the new data.

If you are aware of that you can still use it safely if you can be sure the data won't be modified before you're done with it. In that case you could do something like this:

#define _CRT_SECURE_NO_WARNINGS 1
#include <ctime>
#include <iostream>

int main()
{
    time_t rawtime = time(nullptr);
    tm* timeinfo = localtime(&rawtime);

    std::cout << asctime(timeinfo) << "\n";
    return 0;
}

If you wish to use the more secure localtime_s which populates a structure that you pass in that won't change unexpectedly then you could use it like this:

#include <ctime>
#include <iostream>

int main()
{
    time_t rawtime = time(nullptr);
    tm timeinfo;
    errno_t error = localtime_s(&timeinfo, &rawtime);
    if(error != 0)
    {
        std::cerr << "localtime_s failed.\n";
        return -1;
    }

    std::cout << asctime(&timeinfo) << "\n";
    return 0;
}

Keep in mind that localtime_s may not be available on all platforms so it could be less portable.

Retired Ninja
  • 4,785
  • 3
  • 25
  • 35
  • The other platforms that matter have `localtime_r`... because static local buffers really are a bad idea. The only difference besides the name is that `localtime_r` switches the two arguments... and a macro can easily fix that. – Ben Voigt Mar 16 '15 at 03:12
  • That's true, although they may also have `localtime_s` if they support C11. – Retired Ninja Mar 16 '15 at 03:12
  • Oh weird, I expected the `_r` version to become standard, but they chose the Microsoft one. Well that's cool too. – Ben Voigt Mar 16 '15 at 03:14
  • 2
    Well, it's sorta both. It's named `localtime_s` but it returns a pointer like the posix version rather than the error code of the Microsoft version. It's kind of a mess. – Retired Ninja Mar 16 '15 at 03:15
  • 1
    And the C11 standard variant of `localtime_s()` is defined in ISO/IEC 9899:2011 Annex K.3.8.2.4 as `struct tm *localtime_s(const time_t * restrict timer, struct tm * restrict result);`, compared with MSDN [`localtime_s()`](https://msdn.microsoft.com/en-us/library/a442x3ye.aspx) defining `errno_t localtime_s( struct tm* _tm, const time_t *time );`. See also [Do you use the TR-24731 'safe' functions?](http://stackoverflow.com/questions/372980/do-you-use-the-tr-24731-safe-functions) I wasn't previously aware of this set of differences. – Jonathan Leffler Mar 16 '15 at 03:39
  • @JonathanLeffler: So the signature is exactly the `localtime_r` signature (parameter order and return value), but they took the `localtime_s` name? That is... unfortunate. – Ben Voigt Mar 16 '15 at 04:05
  • 1
    @BenVoigt: The C standard `localtime_s()` name has the same signature as POSIX `localtime_r()`. The Microsoft implementation of the `*_s()` functions was, AFAICT, set in stone (by being released) and submitted to the C standard committee, and the committee made sensible changes — but the damage was done because MS had already released their variant. It is an incredible mess, and very unfortunate indeed. – Jonathan Leffler Mar 16 '15 at 04:10
  • Changing the signature would have been fine if only they'd also changed the name. Now it is impossible to use these functions in portable code. (I place the blame on the C standard committee -- Microsoft doesn't have a time machine, as Raymond Chen keeps reminding us) – Ben Voigt Mar 16 '15 at 04:13