Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. crash in QJsonDocument::fromJson

crash in QJsonDocument::fromJson

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 6 Posters 385 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    JayceGao
    wrote on last edited by
    #1

    Here is the code:

    static bool getObjFromJson(const QString& json, QJsonObject& jsonObj) {
    QJsonParseError jsonParseError;
    QJsonDocument jsonDoc =
    QJsonDocument::fromJson(json.toUtf8(), &jsonParseError);

    if (jsonParseError.error != QJsonParseError::NoError) {
    return false;
    }

    jsonObj = jsonDoc.object();
    return true;
    }

    sometimes, I get crash like this:

    02 00dbcb48 53cfe2a2 35f79300 00dbce88 00dbcbac ucrtbase!_errno+0x1c
    03 00dbcb5c 53cf14c0 35525408 00dbcb7c 0000000a Qt5Core!qstrtoll+0x12 [D:\code\hoyo-qt\qtbase\src\corelib\text\qlocale_tools.cpp @ 442]
    04 00dbcb7c 53cedfd8 35525401 0000000a 00dbcbf3 Qt5Core!QLocaleData::bytearrayToLongLong+0x20 [D:\code\hoyo-qt\qtbase\src\corelib\text\qlocale.cpp @ 4201]
    05 (Inline) -------- -------- -------- -------- Qt5Core!toIntegral_helper+0x18 [D:\code\hoyo-qt\qtbase\src\corelib\text\qbytearray.cpp @ 3819]
    06 (Inline) -------- -------- -------- -------- Qt5Core!toIntegral_helper+0x18 [D:\code\hoyo-qt\qtbase\src\corelib\text\qbytearray.cpp @ 3840]
    07 00dbcbac 53e6aa82 00dbcbf3 0000000a 9e1e0cb4 Qt5Core!QByteArray::toLongLong+0x48 [D:\code\hoyo-qt\qtbase\src\corelib\text\qbytearray.cpp @ 3871]
    08 00dbcc00 53e6b57c 9e1e0c80 00dbce88 00000000 Qt5Core!QJsonPrivate::Parser::parseNumber+0x142 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 755]
    09 00dbcc34 53e6acc8 9e1e0cec 36014cbf 35f792f3 Qt5Core!QJsonPrivate::Parser::parseValue+0x2ac [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 680]
    0a (Inline) -------- -------- -------- -------- Qt5Core!QJsonPrivate::Parser::parseMember+0x34 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 534]
    0b 00dbcc58 53e6b521 9e1e0c38 00dbce88 00000000 Qt5Core!QJsonPrivate::Parser::parseObject+0xc8 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 489]
    0c 00dbcc8c 53e6acc8 9e1e0c04 36014cbf 35f789a1 Qt5Core!QJsonPrivate::Parser::parseValue+0x251 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 667]
    0d (Inline) -------- -------- -------- -------- Qt5Core!QJsonPrivate::Parser::parseMember+0x34 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 534]
    0e 00dbccb0 53e6b521 9e1e0c50 00dbce88 00000000 Qt5Core!QJsonPrivate::Parser::parseObject+0xc8 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 489]
    0f 00dbcce4 53e6acc8 9e1e0dbc 36014cbf 35f7886c Qt5Core!QJsonPrivate::Parser::parseValue+0x251 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 667]
    10 (Inline) -------- -------- -------- -------- Qt5Core!QJsonPrivate::Parser::parseMember+0x34 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 534]
    11 00dbcd08 53e6b521 9e1e0d88 00dbce88 00000000 Qt5Core!QJsonPrivate::Parser::parseObject+0xc8 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 489]
    12 00dbcd3c 53e6acc8 9e1e0dd4 36014cbf 35f778d8 Qt5Core!QJsonPrivate::Parser::parseValue+0x251 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 667]
    13 (Inline) -------- -------- -------- -------- Qt5Core!QJsonPrivate::Parser::parseMember+0x34 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 534]
    14 00dbcd60 53e6b521 9e1e0d20 00dbce88 00000000 Qt5Core!QJsonPrivate::Parser::parseObject+0xc8 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 489]
    15 00dbcd94 53e6a846 9e1e0d0c 00dbce88 35f62056 Qt5Core!QJsonPrivate::Parser::parseValue+0x251 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 667]
    16 00dbcdb8 53e6b4dd 9e1e0d58 00dbce88 00000000 Qt5Core!QJsonPrivate::Parser::parseArray+0xf6 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 567]
    17 00dbcdec 53e6acc8 9e1e0ea4 00dbce88 00dbce9c Qt5Core!QJsonPrivate::Parser::parseValue+0x20d [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 659]
    18 (Inline) -------- -------- -------- -------- Qt5Core!QJsonPrivate::Parser::parseMember+0x34 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 534]
    19 00dbce10 53e6a615 9e1e0ed8 01136248 00dbcef0 Qt5Core!QJsonPrivate::Parser::parseObject+0xc8 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 489]
    1a 00dbce6c 53e611e1 00dbcea0 00dbcee4 9e1e0e74 Qt5Core!QJsonPrivate::Parser::parse+0x1b5 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsonparser.cpp @ 345]
    1b 00dbcec0 783b1419 00dbcef0 00dbceec 00dbcee4 Qt5Core!QJsonDocument::fromJson+0x71 [D:\code\hoyo-qt\qtbase\src\corelib\serialization\qjsondocument.cpp @ 517]

    It happens on Windows.
    Can anyone know why?

    1 Reply Last reply
    0
    • C Offline
      C Offline
      ChrisW67
      wrote on last edited by
      #2

      Welcome to the forum.

      You appear to have a common C++ programming mistake: holding/returning a reference to temporary object.

      jsonObj refers to the temporary QJsonObject returned by jsonDoc.object(). QJsonObject is an implicitly shared class, and shares the data with the document it has been created from. Both jsondoc and the temporary object are destroyed at function exit. Using the reference afterward is a bad idea.

      J 1 Reply Last reply
      2
      • C ChrisW67

        Welcome to the forum.

        You appear to have a common C++ programming mistake: holding/returning a reference to temporary object.

        jsonObj refers to the temporary QJsonObject returned by jsonDoc.object(). QJsonObject is an implicitly shared class, and shares the data with the document it has been created from. Both jsondoc and the temporary object are destroyed at function exit. Using the reference afterward is a bad idea.

        J Offline
        J Offline
        JayceGao
        wrote on last edited by
        #3

        @ChrisW67
        Hi ChrisW67,

        Thanks for your welcome and your input! I appreciate you taking the time to look at my code.

        I understand your concern about returning a reference to a temporary object, and in general C++ programming, you are absolutely right, it's usually a bad practice and can lead to dangling references.

        However, in this specific case with Qt's QJsonObject, I believe the situation is different due to its implicit sharing (copy-on-write) mechanism. jsonDoc.object() does return a temporary QJsonObject, but assigning it to jsonObj (which is a reference parameter) doesn't actually mean jsonObj is directly referencing a temporary object that will be immediately destroyed and become invalid.

        Because QJsonObject is implicitly shared, the assignment jsonObj = jsonDoc.object(); results in jsonObj sharing the data of the JSON object with jsonDoc. It's not a deep copy in the traditional sense, but rather a shallow copy and a reference count increment. The underlying JSON data will be valid as long as either jsonDoc or jsonObj (or any other QJsonObject sharing the same data) is alive. Since jsonObj is passed by reference and exists in the calling scope outside of this function, the data it refers to will remain valid even after getObjFromJson returns and jsonDoc is destroyed.

        Therefore, I believe in this specific scenario, the code is safe and doesn't suffer from the dangling reference issue you mentioned, precisely because of QJsonObject's implicit sharing.

        Regarding the crash I'm experiencing, I suspect it might be caused by something else, perhaps issues within the JSON data itself causing problems during parsing within Qt's internal functions like QLocaleData::bytearrayToLongLong or QJsonPrivate::Parser::parseNumber. The crash stack seems to point towards number parsing issues within Qt's JSON parsing logic.

        Could you (or anyone else) perhaps shed more light on whether my understanding of QJsonObject's implicit sharing in this context is correct? And if so, any ideas on what else might be causing the crash based on the stack trace?

        Thanks again for your help!

        Best regards,

        JayceGao

        Christian EhrlicherC 1 Reply Last reply
        0
        • J JayceGao

          @ChrisW67
          Hi ChrisW67,

          Thanks for your welcome and your input! I appreciate you taking the time to look at my code.

          I understand your concern about returning a reference to a temporary object, and in general C++ programming, you are absolutely right, it's usually a bad practice and can lead to dangling references.

          However, in this specific case with Qt's QJsonObject, I believe the situation is different due to its implicit sharing (copy-on-write) mechanism. jsonDoc.object() does return a temporary QJsonObject, but assigning it to jsonObj (which is a reference parameter) doesn't actually mean jsonObj is directly referencing a temporary object that will be immediately destroyed and become invalid.

          Because QJsonObject is implicitly shared, the assignment jsonObj = jsonDoc.object(); results in jsonObj sharing the data of the JSON object with jsonDoc. It's not a deep copy in the traditional sense, but rather a shallow copy and a reference count increment. The underlying JSON data will be valid as long as either jsonDoc or jsonObj (or any other QJsonObject sharing the same data) is alive. Since jsonObj is passed by reference and exists in the calling scope outside of this function, the data it refers to will remain valid even after getObjFromJson returns and jsonDoc is destroyed.

          Therefore, I believe in this specific scenario, the code is safe and doesn't suffer from the dangling reference issue you mentioned, precisely because of QJsonObject's implicit sharing.

          Regarding the crash I'm experiencing, I suspect it might be caused by something else, perhaps issues within the JSON data itself causing problems during parsing within Qt's internal functions like QLocaleData::bytearrayToLongLong or QJsonPrivate::Parser::parseNumber. The crash stack seems to point towards number parsing issues within Qt's JSON parsing logic.

          Could you (or anyone else) perhaps shed more light on whether my understanding of QJsonObject's implicit sharing in this context is correct? And if so, any ideas on what else might be causing the crash based on the stack trace?

          Thanks again for your help!

          Best regards,

          JayceGao

          Christian EhrlicherC Online
          Christian EhrlicherC Online
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by Christian Ehrlicher
          #4

          @JayceGao said in crash in QJsonDocument::fromJson:

          Therefore, I believe in this specific scenario, the code is safe and doesn't suffer from the dangling reference issue you mentioned, precisely because of QJsonObject's implicit sharing.

          You are wrong. References and implicit sharing are two different things. Fix your code.
          Assigning something to a reference does nothing with the object itself and therefore no refcount can be increased or decreased.

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          J 1 Reply Last reply
          1
          • Christian EhrlicherC Christian Ehrlicher

            @JayceGao said in crash in QJsonDocument::fromJson:

            Therefore, I believe in this specific scenario, the code is safe and doesn't suffer from the dangling reference issue you mentioned, precisely because of QJsonObject's implicit sharing.

            You are wrong. References and implicit sharing are two different things. Fix your code.
            Assigning something to a reference does nothing with the object itself and therefore no refcount can be increased or decreased.

            J Offline
            J Offline
            JayceGao
            wrote on last edited by JayceGao
            #5

            Hi again,

            Thanks for the continued discussion. To provide more context, here's how I typically use this function in my code:

            QString json = ""; // some json text
            QJsonObject json_obj;
            bool parsed = getObjFromJson(json, json_obj);

            // other code using json_obj ...
            C++
            This pattern is used extensively throughout my project, and in the vast majority of cases, it works without any issues. The crash I reported is an occasional occurrence, which makes me wonder if this common usage pattern itself could be problematic, even if it seems to work most of the time.

            Could you please advise if this typical usage scenario might still have potential issues, despite the implicit sharing of QJsonObject? Or is it more likely that the occasional crashes are indeed related to the content of the json string being parsed, or perhaps some other factor unrelated to the function's structure and temporary object handling?

            Thank you again for your insights.

            Best regards,

            JayceGao

            JonBJ 1 Reply Last reply
            0
            • J JayceGao

              Hi again,

              Thanks for the continued discussion. To provide more context, here's how I typically use this function in my code:

              QString json = ""; // some json text
              QJsonObject json_obj;
              bool parsed = getObjFromJson(json, json_obj);

              // other code using json_obj ...
              C++
              This pattern is used extensively throughout my project, and in the vast majority of cases, it works without any issues. The crash I reported is an occasional occurrence, which makes me wonder if this common usage pattern itself could be problematic, even if it seems to work most of the time.

              Could you please advise if this typical usage scenario might still have potential issues, despite the implicit sharing of QJsonObject? Or is it more likely that the occasional crashes are indeed related to the content of the json string being parsed, or perhaps some other factor unrelated to the function's structure and temporary object handling?

              Thank you again for your insights.

              Best regards,

              JayceGao

              JonBJ Online
              JonBJ Online
              JonB
              wrote on last edited by JonB
              #6

              @JayceGao
              Your code as shown is fine, so long as you only use the QJsonObject json_obj; and its corresponding QJsonDocument jsonDoc within the scope it is declared, e.g. if this is in a function until the end of that function. What is wrong in your original is that you have a reference parameter QJsonObject& jsonObj to your function, and that gets assigned to the result of jsonDoc.object(), which itself is an object in the QJsonDocument jsonDoc. Nothing copies that object. So on exit from the function it references an object which has been destroyed.

              It is possible that it "works" from time to time depending on what has happened to the memory holding the object since the function was exited. The behaviour is of course "undefined" ("UB"): as soon as the memory gets clobbered crashes are likely, if the memory happens not to have been overwritten/used elsewhere it will appear to work. That might be why you see an "intermittent" problem.

              Btw, it is unlikely that Qt JSON code would "crash" on encountering malformed or problematic JSON text to parse. That would be a bug in Qt code. Rather you should find that the parse() (fromJson()) call returns failure and sets a QJsonParseError you can examine, if that happened.

              J 1 Reply Last reply
              0
              • JonBJ JonB

                @JayceGao
                Your code as shown is fine, so long as you only use the QJsonObject json_obj; and its corresponding QJsonDocument jsonDoc within the scope it is declared, e.g. if this is in a function until the end of that function. What is wrong in your original is that you have a reference parameter QJsonObject& jsonObj to your function, and that gets assigned to the result of jsonDoc.object(), which itself is an object in the QJsonDocument jsonDoc. Nothing copies that object. So on exit from the function it references an object which has been destroyed.

                It is possible that it "works" from time to time depending on what has happened to the memory holding the object since the function was exited. The behaviour is of course "undefined" ("UB"): as soon as the memory gets clobbered crashes are likely, if the memory happens not to have been overwritten/used elsewhere it will appear to work. That might be why you see an "intermittent" problem.

                Btw, it is unlikely that Qt JSON code would "crash" on encountering malformed or problematic JSON text to parse. That would be a bug in Qt code. Rather you should find that the parse() (fromJson()) call returns failure and sets a QJsonParseError you can examine, if that happened.

                J Offline
                J Offline
                JayceGao
                wrote on last edited by
                #7

                @JonB Thanks I will check my code again.

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Hi,

                  One thing you could do is use the swap function.

                  Other possibilities, return the QJsonObject and pass the Boolean as output parameter (like for example the QString conversion functions).

                  Use std::optional for the return value so you don't need an output parameter.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • Christian EhrlicherC Online
                    Christian EhrlicherC Online
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    Since QJsonObject() has a function isEmpty() I don't see why you can't simply return a QJsonObject

                    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                    Visit the Qt Academy at https://academy.qt.io/catalog

                    SGaistS 1 Reply Last reply
                    0
                    • Christian EhrlicherC Christian Ehrlicher

                      Since QJsonObject() has a function isEmpty() I don't see why you can't simply return a QJsonObject

                      SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      @Christian-Ehrlicher one possible reason that comes to mind: empty does not imply failure to load the json data and it might be a valid case.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      0
                      • Axel SpoerlA Offline
                        Axel SpoerlA Offline
                        Axel Spoerl
                        Moderators
                        wrote on last edited by
                        #11

                        Return the QJsonObject and pass a pointer to a boolean to set a result, if necessary at all.

                        static QJsonObject getObjFromJson(const QString &json, bool *ok = nullptr)
                        {
                            QJsonParseError jsonParseError;
                            const QJsonDocument jsonDoc = QJsonDocument::fromJson(json.toUtf8(), &jsonParseError);
                            const bool result = jsonParseError.error == QJsonParseError::NoError;
                            if (ok)
                                *ok = result;    
                            return jsonDoc.object();
                         }

                        Software Engineer
                        The Qt Company, Oslo

                        1 Reply Last reply
                        1

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved