Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qt 5.15.0 MSVC2019 16.6.2: Global QFile instance causes [ASSERT: "theMainThread.loadRelaxed() != nullptr" in file kernel\qcoreapplication.cpp, line 536] in Debug build



  • Hello,

    I had a somewhat similarly odd, though less critical, issue with QString on an older version of Qt in the past that I posted about where someone commented that it was likely due to an extremely niche incompatibility with the MSVC compiler that there was nothing I could do about. I expect the same case in this situation, but figured I'd see if anyone else has run into this.

    It is really quite simple. Having a global QFile instance of any kind within the title environment causes the following assertion to fail:695515ed-816a-4d14-9ef7-5f0101ae17fd-image.png

    For example:

    #include <QFile>
    #include <QApplication>
    
    const QFile test("Test");
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        return 0;
    }
    

    This assertion fails as soon as the process attempts to move past the declaration/initialization of "app" (which makes sense since the assertion lies within QCoreApplication).

    This only happens in Debug builds and not Release ones, since asserts are ignored by default in said compiler mode. I'd imagine there could easily be undefined/unwanted behavior anyway, not to mention it makes debugging such a project impossible.

    This does not happen with similar QObjects like QDir and QFileInfo.

    Ultimately I can just use const QString and create the QFile instances within main, it isn't a huge deal, but it would be convenient and simply things a bit if I could use const QFile's globally. Since this is my second time running into strange issues (before it was that the app would crash on exit when any static inline QString was used within a class) using Qt objects in non-function scopes, I wonder if this is just a common problem with MSVC that is hard to test for in each build or if I've just tried to use Qt at coincidental times that these issues have existed. I only mention this because for that other issue someone using the same setup but with MinGW couldn't reproduce the problem.

    Again just curious if anyone else has had issues like this.


  • Qt Champions 2019

    @oblivioncth Why do you need a global QFile instance?
    You should never create QObject based instances before QApplication instance is created!


  • Qt Champions 2019

    @oblivioncth Why do you need a global QFile instance?
    You should never create QObject based instances before QApplication instance is created!


  • Moderators

    @oblivioncth

    @jsulm is absolutely correct File is a QObject at it's core and you mustn't create a QObject before the QApplication instance!
    QDir and QFileInfo are not QObjects so they will work just fine.

    Btw this is also true for statics, and you should get a compiler warning/error when you make a static QFile that it is created before the application instance (I've seen it there myself :D)


    edit:No warning for statics, that was for static QImage, which is a totally different situation, my bad



  • @jsulm said in Qt 5.15.0 MSVC2019 16.6.2: Global QFile instance causes [ASSERT: "theMainThread.loadRelaxed() != nullptr" in file kernel\qcoreapplication.cpp, line 536] in Debug build:

    @oblivioncth Why do you need a global QFile instance?
    You should never create QObject based instances before QApplication instance is created!

    Well at least this time this is intended behavior and not a compiler bug, but I wish it was more apparent that was what was causing the problem since I ended up having to remove things from my application one-by-one to figure it out (though I had a hunch it was these instances causing the problem all along).

    Clearly this is a core rule of Qt (not using QObjects before QCoreApplication or one of its children have been created, and now that you mention it that does actually sound vaguely familiar. I guess I forgot about it since I starting using Qt back in 3.x and haven't wanted to make a QObject before creating a QCoreApplication instance.

    I wanted to make them because the application I producing is a CLI for another program and there are numerous helper programs that said target program needs to interact with that have fixed locations relative to itself. Since my app is designed to reside right next to the original app without a CLI it to will have a fixed position relative to these helper applications and so it was the most straightforward to define them as const files via QFile using their relative paths, i.e.

    const QFile("/sub-folder1/sub-folder2/sub-app-1.exe");
    ...
    

    I also was going to do this for some log files that are in a fixed location so have easy go-to instances to pass to other methods for writing to and reading from them.

    To be fair, this is primarily so I can use them in the one constructor of QFileInfo to make use of its methods like "fileName()" to get just the name of the file without the proceeding path, a class that also has a constructor that accepts the path itself via QString. So yes, I can either just make the QFile instance after making my QApplication instance, or forgo it entirely and just use a const QString and use that to create the QFile instances I need.

    When making Qt applications I like to make use of QFile and QDir when what I'm dealing with are references to files and directories as it makes the code a bit more readable and deterministic, even if I'm not making use of all the features of these classes, as it makes it easy to start using those features in future development if I end up needing them.

    For example in a Qt based library I've made I have some functions that perform specific operations to files based on the input arguments and as the reference to the file itself I have those functions take a QFile instance by reference as it just "makes sense" for a function that is designed to interact with a file, even though I could just pass a QString that contains the path to the file and it would work just the same. A string can be anything, and while QFile doesn't actually enforce that its filePath points to an actual file, it still reinforces the idea that at that point in time in the code you're supposed to be providing/dealing with a "file" and not just any string.

    So its just a minor OCD thing for organization and readability lol.

    @J-Hilk said in Qt 5.15.0 MSVC2019 16.6.2: Global QFile instance causes [ASSERT: "theMainThread.loadRelaxed() != nullptr" in file kernel\qcoreapplication.cpp, line 536] in Debug build:

    @oblivioncth

    @jsulm is absolutely correct File is a QObject at it's core and you mustn't create a QObject before the QApplication instance!
    QDir and QFileInfo are not QObjects so they will work just fine.

    Btw this is also true for statics, and you should get a compiler warning/error when you make a static QFile that it is created before the application instance (I've seen it there myself :D)


    edit:No warning for statics, that was for static QImage, which is a totally different situation, my bad

    Sadly I did not get a warning for creating a QObject instance before QApplication, which would have identified the bug right away. Small chance it's related to the current issue of Qt Creator 14.2.3 using Clang 8.x when after a update to Visual Studio 16 it requires Clang 10 to avoid issues with parsing your source files (https://bugreports.qt.io/browse/QTCREATORBUG-23800), though it is probably just more so a weird thing with MSVC in general or something with my settings.

    Anyway thanks both of you, I can now know this was a simple oversight on my part, despite the annoyance in finding it due to that warning not showing.



  • Hmm, while I do see some things like stackoverflow questions in which people note that created QObjects before QApplication is not supported, others say just that UI features and some static methods will not work. Additionally, the documentation for QApplication only days it must be created before any UI related objects are made, which QFile is not (at least it doesn't appear to have any ties to the UI cycle).

    https://doc.qt.io/qt-5/qapplication.html#details
    Is there anywhere else that describes this limitation in more detail/more directly?