0

I tried to log std::exit calls in my GCC10 compiled Qt 5 application. This fails when turning a QDateTime object into a string. It can be reproduced with the following snippet:

void exitHandler() noexcept
{
   QString b = QDateTime::currentDateTime().toString();
}

int main(int pArgc, char* pArgv[]) noexcept
{
   std::atexit(&exitHandler);
   QString a = QDateTime::currentDateTime().toString();
   std::exit(1);

   return 0;
}

Variable a contains the expected date/time while variable b is empty. When using UTC time, b is " GMT". I am not aware of any related restrictions of exit-handlers.

Can someone tell me what is going wrong here?

Silicomancer
  • 8,604
  • 10
  • 63
  • 130
  • 1
    which platform / os? Which Qt version? – Waqar Jun 18 '20 at 12:57
  • Cannot reproduce the bug. It works fine for me (Windows 10, Qt 5.12.1) – Fareanor Jun 18 '20 at 13:02
  • not reproducible, both `a` and `b` have value, Working as expected. – Waqar Jun 18 '20 at 13:02
  • How do you get the value of `b`? Maybe your method is incorrect? – vahancho Jun 18 '20 at 13:42
  • Have managed to repro. this on Suse Linux with g++ 10.1.1 and Qt5.15.0. No obvious reason for the behaviour though. I suppose it's possible that certain state used by `QDateTime::toString()` has already been de-initialized by an exit handler registered elsewhere by Qt. – G.M. Jun 18 '20 at 13:54
  • KDE Neon 18.04, Qt 5.14.2. I tried writing the string to std::cout and inspecting it with the debugger. – Silicomancer Jun 18 '20 at 17:57
  • @G.M. Thanks a lot, so it isn't just me. If no one here knows more, I will ask on the Qt mailing list. Exit handlers are executed in the reverse order of registration, so I don't know how a Qt handler could have been executed first. – Silicomancer Jun 18 '20 at 18:00
  • 1
    I think @G.M. is right. Exit handlers are called after deinitialization of static variables. QDateTime.cpp contains at least one static lookup table for the days of the week. There might be more accesses to static variables on the whole call stack. – Richard W Jun 19 '20 at 20:44
  • @RichardW G.M. was not completely right. Reason isn't another exit handler. In the ML it was confirmed that your idea is right and deletion of static data is the reason. Very interesting. Please turn you comment into an answer so I can accept it. – Silicomancer Jun 20 '20 at 19:51

1 Answers1

1

Exit handlers are called after deinitialization of static variables and thus it is unsafe to call functions that might access static variables.

qdatetime.cpp for instance contains at least one static lookup table for the days of the week which is probably used by toString(). There might be more accesses to (already destroyed) static variables on the call stack.

If you really need this kind of information in the exit handler, you may allocate a static array of chars (without new) and write the date string there from within the main function. I haven't tried but I would expect that memory in the .bss segment is not zeroed on exit and accessing it after global deinitialization is still safe.

Richard W
  • 631
  • 4
  • 15