Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-62693

Initialization of staticMetaObject (MSVC2017)

    XMLWordPrintable

    Details

      Description

      I tried building our code with VS2017 x86_amd64 debug today. It compiled find, but when I started it, it immediately crashed.

      Further investigation showed, that a static QObject derived class called connect, while the staticMetaObject of the sender was not initialized (or 0-initialized).

      According to the standard all static initialization should take place, before dynamic initialization. Looking at the QMetaObject, it looked like it qualifies for static initialization and most of the time it does.

      The problem is the QBasicAtomicInt, which has a constexpr constructor, that is used during construction of the QMetaObject. I think the whole QMetaObject still qualifies for static initialization according to the standard, but MSVC2017 in debug mode disagrees. It decides to perform dynamic initialization leading to unspecified initialization order, if the two static objects are in different compilation units (which is almost always the case for staticMetaObject).

       

      I am not really sure, if this is a compiler bug, I will file a bugreport at MS connect. In the meantime, it is also possible to fix this in moc. Just add constexpr to the definition of the staticMetaObject. This forces the compiler to do static initialization even in debug mode and I think it has the advantage of preventing accidental breakage of static initialization for other compilers, if someone modifies e.g. QBasicAtomic. This is actually not possible...

       

      Here is my sample code, that demonstrates the issue:

      #include <iostream>
      
      struct ConstexprStruct {
      	int x;
      	constexpr ConstexprStruct(int x) : x(x) {}
      };
      
      struct Caller {
      	Caller();
      };
      
      
      Caller caller;
      constexpr ConstexprStruct constexp { 42 };
      ConstexprStruct nonconstexp { 42 };
      
      Caller::Caller()
      {
      	std::cout << "constexp:    " << constexp.x << std::endl;
      	std::cout << "nonconstexp: " << nonconstexp.x << std::endl;
      }
      

       The result is:

      constexpr:    42
      nonconstexpr: 0

        Attachments

          Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            Activity

              People

              Assignee:
              ogoffart Olivier Goffart (Woboq GmbH)
              Reporter:
              jvehlow jvehlow
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:

                  Gerrit Reviews

                  There are no open Gerrit changes