For years I've been using std::put_time in a function to write a timestamp to a stream. All my logging statements go through this. It has always worked perfectly:
inline std::ostream& logTime(std::ostream& stm,
const std::chrono::system_clock::time_point& tp)
{
auto time = std::chrono::system_clock::to_time_t(tp);
tm tmVal = {0};
localtime_x(&time, &tmVal);
return stm << std::put_time(&tmVal, "%H:%M:%S"); // Print standard date&time
}
Today when I clicked "close" on my application, it crashed here, right on the use of put_time
. (An object in one of my DLLs was in its destructor and logged a statement). The call stack showed an access violation deep within the guts of put_time
. Visual studio told me that "this" was some clearly invalid value.
I examined the contents of the tm
structure being handed to put_time
and it was clearly valid. So was the stream object. In fact, the object being destroyed was valid too. And the DLL was still loaded.
After some fiddling, in desperation, I tried changed the routine to do a crude approximation of what I wanted without using put_time
by manually dumping the digits to the stream. And now it works, no crashes. But I don't understand what I did wrong.
Here is what I'm doing now:
inline std::ostream& logTime(std::ostream& stm,
const std::chrono::system_clock::time_point& tp)
{
auto time = std::chrono::system_clock::to_time_t(tp);
tm tmVal = {0};
localtime_x(&time, &tmVal);
if (tmVal.tm_hour < 10)
stm << "0";
stm << tmVal.tm_hour;
stm << ':';
if (tmVal.tm_min < 10)
stm << "0";
stm << tmVal.tm_min;
stm << ':';
if (tmVal.tm_sec < 10)
stm << '0';
stm << tmVal.tm_sec;
return stm;
// This is causing access violations on shutdown. DOn't know why
// return stm << std::put_time(&tmVal, "%H:%M:%S"); // Print standard date&time
}
So I have a "fix" but I am left to wonder. Why would this work while put_time
causes a crash? It's a global function, all of its inputs were valid and it otherwise works well. Is this just Microsoft's CRT maybe storing some context that becomes invalid while shutting down?
(I'm using Visual Studio 16.9, with full C++17 compatibility enabled, if it matters)