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. Debug issue FYI
Forum Updated to NodeBB v4.3 + New Features

Debug issue FYI

Scheduled Pinned Locked Moved Unsolved General and Desktop
19 Posts 5 Posters 3.6k Views 2 Watching
  • 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.
  • O Offline
    O Offline
    ofmrew
    wrote on last edited by
    #1

    I was using the following

    QString st = ui->source->toPlainText();   //source is a QPlainTextEdit
    

    it was the last statement and the debugger showed the value to be blank; however, when I added another line, namely:

    qDebug() << st

    did the debugger show the correct value of the string.

    aha_1980A 1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi
      Can it be a out of scope thing?
      Also what platform, Qt version and compiler is this seen on?

      O 1 Reply Last reply
      0
      • mrjjM mrjj

        Hi
        Can it be a out of scope thing?
        Also what platform, Qt version and compiler is this seen on?

        O Offline
        O Offline
        ofmrew
        wrote on last edited by
        #3

        @mrjj Linux Mint 64bit latest version of Qt 5.9
        It was the last statement in a method and it was resolved when the debug statement was added. So I could have been out of scope, but the cursor was pointing to the closing bracket. It would seem to me that the stack should not have been unwound until the thread of execution had exited the method. Since I wasted some time trying to figure out the problem, I will in the future always add a debug statement at the end to prevent a recurrance.

        mrjjM 1 Reply Last reply
        1
        • O ofmrew

          @mrjj Linux Mint 64bit latest version of Qt 5.9
          It was the last statement in a method and it was resolved when the debug statement was added. So I could have been out of scope, but the cursor was pointing to the closing bracket. It would seem to me that the stack should not have been unwound until the thread of execution had exited the method. Since I wasted some time trying to figure out the problem, I will in the future always add a debug statement at the end to prevent a recurrance.

          mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @ofmrew
          Ok, sounds a bit odd.
          Im also on Mint at work i will try it.

          1 Reply Last reply
          0
          • O ofmrew

            I was using the following

            QString st = ui->source->toPlainText();   //source is a QPlainTextEdit
            

            it was the last statement and the debugger showed the value to be blank; however, when I added another line, namely:

            qDebug() << st

            did the debugger show the correct value of the string.

            aha_1980A Offline
            aha_1980A Offline
            aha_1980
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @ofmrew said in Debug issue FYI:

            I was using the following

            QString st = ui->source->toPlainText();   //source is a QPlainTextEdit
            

            it was the last statement and the debugger showed the value to be blank;

            If you assign st as last statement in a function, the compiler may optimize the assignment, because the variable is never read. if you add a qDebug afterwards, it is read.
            So did you check for compiler warnings?

            Qt has to stay free or it will die.

            O 1 Reply Last reply
            2
            • aha_1980A aha_1980

              @ofmrew said in Debug issue FYI:

              I was using the following

              QString st = ui->source->toPlainText();   //source is a QPlainTextEdit
              

              it was the last statement and the debugger showed the value to be blank;

              If you assign st as last statement in a function, the compiler may optimize the assignment, because the variable is never read. if you add a qDebug afterwards, it is read.
              So did you check for compiler warnings?

              O Offline
              O Offline
              ofmrew
              wrote on last edited by
              #6

              @aha_1980 There were no compiler warnings.

              kshegunovK 1 Reply Last reply
              0
              • O ofmrew

                @aha_1980 There were no compiler warnings.

                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by kshegunov
                #7

                If you put the breakpoint at the last } of the function the debugger will break after the stack's been unwound. It's a peculiarity of sorts I've found. When I do mid-work debug run and I have such a case I put an empty statement like int z = 0 and break at it (before it's executed) to get proper debug information.

                Read and abide by the Qt Code of Conduct

                O 1 Reply Last reply
                2
                • kshegunovK kshegunov

                  If you put the breakpoint at the last } of the function the debugger will break after the stack's been unwound. It's a peculiarity of sorts I've found. When I do mid-work debug run and I have such a case I put an empty statement like int z = 0 and break at it (before it's executed) to get proper debug information.

                  O Offline
                  O Offline
                  ofmrew
                  wrote on last edited by
                  #8

                  @kshegunov I tried putting the breakpoint on the opening bracket of the method and the statement itself, same result. It looks like the culprit is no statement between the statement and the closing bracket. Thanks to all for your responses. Is this a bug?

                  kshegunovK JonBJ 2 Replies Last reply
                  0
                  • O ofmrew

                    @kshegunov I tried putting the breakpoint on the opening bracket of the method and the statement itself, same result. It looks like the culprit is no statement between the statement and the closing bracket. Thanks to all for your responses. Is this a bug?

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on last edited by
                    #9

                    @ofmrew said in Debug issue FYI:

                    Is this a bug?

                    I don't know, in my experience it has been like this forever, so I'd assume not, or at worst a minor one. It never really bothered me much, as there's a very simple workaround as I mentioned above.

                    Read and abide by the Qt Code of Conduct

                    1 Reply Last reply
                    0
                    • O ofmrew

                      @kshegunov I tried putting the breakpoint on the opening bracket of the method and the statement itself, same result. It looks like the culprit is no statement between the statement and the closing bracket. Thanks to all for your responses. Is this a bug?

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

                      @ofmrew said in Debug issue FYI:

                      @kshegunov I tried putting the breakpoint on the opening bracket of the method and the statement itself, same result. It looks like the culprit is no statement between the statement and the closing bracket. Thanks to all for your responses. Is this a bug?

                      Most compilers will make certain small "optimizations" on certain pieces of code (e.g. not creating/updating a variable if it's never used), such that the exact instructions do not always correspond one-to-one with what you might expect looking at the source code literally, even if overall optimizations are off. And this is likely to be a compiler generated code rather than debugger issue. When debugging I often have to append a z = z + 1 or str += "" kind-of-statement in the source code at the end of a function if the last statement changed z/str and I want to see the value, varying across compilers/debuggers and languages.

                      BTW, when the last statement in a function is auto variable = function(), why should the compiler generate the code to actually allocate/set the variable at all? If you look at the disassembly code, wouldn't surprise me if the variable part is simply not there.

                      kshegunovK 1 Reply Last reply
                      0
                      • JonBJ JonB

                        @ofmrew said in Debug issue FYI:

                        @kshegunov I tried putting the breakpoint on the opening bracket of the method and the statement itself, same result. It looks like the culprit is no statement between the statement and the closing bracket. Thanks to all for your responses. Is this a bug?

                        Most compilers will make certain small "optimizations" on certain pieces of code (e.g. not creating/updating a variable if it's never used), such that the exact instructions do not always correspond one-to-one with what you might expect looking at the source code literally, even if overall optimizations are off. And this is likely to be a compiler generated code rather than debugger issue. When debugging I often have to append a z = z + 1 or str += "" kind-of-statement in the source code at the end of a function if the last statement changed z/str and I want to see the value, varying across compilers/debuggers and languages.

                        BTW, when the last statement in a function is auto variable = function(), why should the compiler generate the code to actually allocate/set the variable at all? If you look at the disassembly code, wouldn't surprise me if the variable part is simply not there.

                        kshegunovK Offline
                        kshegunovK Offline
                        kshegunov
                        Moderators
                        wrote on last edited by kshegunov
                        #11

                        @JNBarchan said in Debug issue FYI:

                        Most compilers will make certain small "optimizations" on certain pieces of code (e.g. not creating/updating a variable if it's never used), such that the exact instructions do not always correspond one-to-one with what you might expect looking at the source code literally, even if overall optimizations are off.

                        I beg to differ, you can't just optimize the return value out of the assembly because the compiler can't know if this won't create a side effect because of your destructor not being run! Additionally, I have never seen it and I really doubt it is in fact done. Here's an excerpt of the assembly from g++ (7.2.x) for a very simple program compiled without optimization and with debug symbols. This is the C++ code:

                        void function()
                        {
                            QStringList list = QStringList { "1", "2", "3", "4" };
                            QString str = list.last();
                        }
                        

                        This is the assembly for the last line onward.

                                11 [1]	    QString str = list.last();
                        0x555555555896  <+0x00ac>        48 8d 45 b8           lea    -0x48(%rbp),%rax
                        0x55555555589a  <+0x00b0>        48 89 c7              mov    %rax,%rdi
                        0x55555555589d  <+0x00b3>        e8 7c 06 00 00        callq  0x555555555f1e <QList<QString>::last()>
                        0x5555555558a2  <+0x00b8>        48 89 c2              mov    %rax,%rdx
                        0x5555555558a5  <+0x00bb>        48 8d 45 b0           lea    -0x50(%rbp),%rax
                        0x5555555558a9  <+0x00bf>        48 89 d6              mov    %rdx,%rsi
                        0x5555555558ac  <+0x00c2>        48 89 c7              mov    %rax,%rdi
                        0x5555555558af  <+0x00c5>        e8 36 02 00 00        callq  0x555555555aea <QString::QString(QString const&)>
                        0x5555555558b4  <+0x00ca>        48 8d 45 b0           lea    -0x50(%rbp),%rax
                        0x5555555558b8  <+0x00ce>        48 89 c7              mov    %rax,%rdi
                        0x5555555558bb  <+0x00d1>        e8 82 02 00 00        callq  0x555555555b42 <QString::~QString()>
                                10 [2]	    QStringList list = QStringList { "1", "2", "3", "4" };
                        0x5555555558c0  <+0x00d6>        48 8d 45 b8           lea    -0x48(%rbp),%rax
                        0x5555555558c4  <+0x00da>        48 89 c7              mov    %rax,%rdi
                        0x5555555558c7  <+0x00dd>        e8 80 03 00 00        callq  0x555555555c4c <QStringList::~QStringList()>
                                12 [1]	}
                        0x5555555558cc  <+0x00e2>        eb 47                 jmp    0x555555555915 <function()+299>
                        

                        As you can see the compiler doesn't strip or optimize anything here. It will create the string from the QStringList::last's return value and then it will immediately start to unwind the stack (+0x00ca onward). Something more, if one puts a breakpoint exactly at the closing brace } the debugger will break at +0x00e2 exactly after the stack's been unwound. So at least for g++ + gdb (but I imagine for other compilers and debuggers too) it's not the compiler stripping anything, it's just where the break is placed in the assembly.

                        Read and abide by the Qt Code of Conduct

                        JonBJ O 2 Replies Last reply
                        1
                        • kshegunovK kshegunov

                          @JNBarchan said in Debug issue FYI:

                          Most compilers will make certain small "optimizations" on certain pieces of code (e.g. not creating/updating a variable if it's never used), such that the exact instructions do not always correspond one-to-one with what you might expect looking at the source code literally, even if overall optimizations are off.

                          I beg to differ, you can't just optimize the return value out of the assembly because the compiler can't know if this won't create a side effect because of your destructor not being run! Additionally, I have never seen it and I really doubt it is in fact done. Here's an excerpt of the assembly from g++ (7.2.x) for a very simple program compiled without optimization and with debug symbols. This is the C++ code:

                          void function()
                          {
                              QStringList list = QStringList { "1", "2", "3", "4" };
                              QString str = list.last();
                          }
                          

                          This is the assembly for the last line onward.

                                  11 [1]	    QString str = list.last();
                          0x555555555896  <+0x00ac>        48 8d 45 b8           lea    -0x48(%rbp),%rax
                          0x55555555589a  <+0x00b0>        48 89 c7              mov    %rax,%rdi
                          0x55555555589d  <+0x00b3>        e8 7c 06 00 00        callq  0x555555555f1e <QList<QString>::last()>
                          0x5555555558a2  <+0x00b8>        48 89 c2              mov    %rax,%rdx
                          0x5555555558a5  <+0x00bb>        48 8d 45 b0           lea    -0x50(%rbp),%rax
                          0x5555555558a9  <+0x00bf>        48 89 d6              mov    %rdx,%rsi
                          0x5555555558ac  <+0x00c2>        48 89 c7              mov    %rax,%rdi
                          0x5555555558af  <+0x00c5>        e8 36 02 00 00        callq  0x555555555aea <QString::QString(QString const&)>
                          0x5555555558b4  <+0x00ca>        48 8d 45 b0           lea    -0x50(%rbp),%rax
                          0x5555555558b8  <+0x00ce>        48 89 c7              mov    %rax,%rdi
                          0x5555555558bb  <+0x00d1>        e8 82 02 00 00        callq  0x555555555b42 <QString::~QString()>
                                  10 [2]	    QStringList list = QStringList { "1", "2", "3", "4" };
                          0x5555555558c0  <+0x00d6>        48 8d 45 b8           lea    -0x48(%rbp),%rax
                          0x5555555558c4  <+0x00da>        48 89 c7              mov    %rax,%rdi
                          0x5555555558c7  <+0x00dd>        e8 80 03 00 00        callq  0x555555555c4c <QStringList::~QStringList()>
                                  12 [1]	}
                          0x5555555558cc  <+0x00e2>        eb 47                 jmp    0x555555555915 <function()+299>
                          

                          As you can see the compiler doesn't strip or optimize anything here. It will create the string from the QStringList::last's return value and then it will immediately start to unwind the stack (+0x00ca onward). Something more, if one puts a breakpoint exactly at the closing brace } the debugger will break at +0x00e2 exactly after the stack's been unwound. So at least for g++ + gdb (but I imagine for other compilers and debuggers too) it's not the compiler stripping anything, it's just where the break is placed in the assembly.

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

                          @kshegunov
                          I do bow to your greater knowledge in this area. I did not mean that the destructor was not to be run, I meant I was not sure that the space on he stack for the variable str would necessarily be allocated. Does the disassembly show the return value being stored into str?

                          Not that it matters, but I am mighty confused at that disassembly for the source code you show at the top. They are correctly in sync, aren't they? EDIT: OIC, the disassembler shows the corresponding source line for the QStringList destructor --- wow, OK!

                          kshegunovK 1 Reply Last reply
                          0
                          • kshegunovK kshegunov

                            @JNBarchan said in Debug issue FYI:

                            Most compilers will make certain small "optimizations" on certain pieces of code (e.g. not creating/updating a variable if it's never used), such that the exact instructions do not always correspond one-to-one with what you might expect looking at the source code literally, even if overall optimizations are off.

                            I beg to differ, you can't just optimize the return value out of the assembly because the compiler can't know if this won't create a side effect because of your destructor not being run! Additionally, I have never seen it and I really doubt it is in fact done. Here's an excerpt of the assembly from g++ (7.2.x) for a very simple program compiled without optimization and with debug symbols. This is the C++ code:

                            void function()
                            {
                                QStringList list = QStringList { "1", "2", "3", "4" };
                                QString str = list.last();
                            }
                            

                            This is the assembly for the last line onward.

                                    11 [1]	    QString str = list.last();
                            0x555555555896  <+0x00ac>        48 8d 45 b8           lea    -0x48(%rbp),%rax
                            0x55555555589a  <+0x00b0>        48 89 c7              mov    %rax,%rdi
                            0x55555555589d  <+0x00b3>        e8 7c 06 00 00        callq  0x555555555f1e <QList<QString>::last()>
                            0x5555555558a2  <+0x00b8>        48 89 c2              mov    %rax,%rdx
                            0x5555555558a5  <+0x00bb>        48 8d 45 b0           lea    -0x50(%rbp),%rax
                            0x5555555558a9  <+0x00bf>        48 89 d6              mov    %rdx,%rsi
                            0x5555555558ac  <+0x00c2>        48 89 c7              mov    %rax,%rdi
                            0x5555555558af  <+0x00c5>        e8 36 02 00 00        callq  0x555555555aea <QString::QString(QString const&)>
                            0x5555555558b4  <+0x00ca>        48 8d 45 b0           lea    -0x50(%rbp),%rax
                            0x5555555558b8  <+0x00ce>        48 89 c7              mov    %rax,%rdi
                            0x5555555558bb  <+0x00d1>        e8 82 02 00 00        callq  0x555555555b42 <QString::~QString()>
                                    10 [2]	    QStringList list = QStringList { "1", "2", "3", "4" };
                            0x5555555558c0  <+0x00d6>        48 8d 45 b8           lea    -0x48(%rbp),%rax
                            0x5555555558c4  <+0x00da>        48 89 c7              mov    %rax,%rdi
                            0x5555555558c7  <+0x00dd>        e8 80 03 00 00        callq  0x555555555c4c <QStringList::~QStringList()>
                                    12 [1]	}
                            0x5555555558cc  <+0x00e2>        eb 47                 jmp    0x555555555915 <function()+299>
                            

                            As you can see the compiler doesn't strip or optimize anything here. It will create the string from the QStringList::last's return value and then it will immediately start to unwind the stack (+0x00ca onward). Something more, if one puts a breakpoint exactly at the closing brace } the debugger will break at +0x00e2 exactly after the stack's been unwound. So at least for g++ + gdb (but I imagine for other compilers and debuggers too) it's not the compiler stripping anything, it's just where the break is placed in the assembly.

                            O Offline
                            O Offline
                            ofmrew
                            wrote on last edited by
                            #13

                            @kshegunov I your response you indicated it was where the break was placed. It does not seem to matter in this case: there is a single statement and the break can be place at the beginning, at the end or on the statement, the results are the same, nothing shows in the string. Maybe the problem is not with the placement of the breakpoint, but with the fact that it is a single statement--grasping for straws!

                            1 Reply Last reply
                            0
                            • JonBJ JonB

                              @kshegunov
                              I do bow to your greater knowledge in this area. I did not mean that the destructor was not to be run, I meant I was not sure that the space on he stack for the variable str would necessarily be allocated. Does the disassembly show the return value being stored into str?

                              Not that it matters, but I am mighty confused at that disassembly for the source code you show at the top. They are correctly in sync, aren't they? EDIT: OIC, the disassembler shows the corresponding source line for the QStringList destructor --- wow, OK!

                              kshegunovK Offline
                              kshegunovK Offline
                              kshegunov
                              Moderators
                              wrote on last edited by kshegunov
                              #14

                              @JNBarchan said in Debug issue FYI:

                              Does the disassembly show the return value being stored into str?

                              Yes, the value is stored (through a call to the copy constructor) to -0x50(%rbp) which is the QString object. And after that the destructor is called for that object at +0x00d1 (the actual object's address is loaded just above at +0x00ca).

                              They are correctly in sync, aren't they?

                              Yes, absolutely. That one was pulled from the "Operate by instruction" view in Qt Creator.

                              @ofmrew said in Debug issue FYI:

                              Maybe the problem is not with the placement of the breakpoint, but with the fact that it is a single statement--grasping for straws!

                              In fact it is, look at the two screenshots bellow and you'll see how the breakpoints are placed in code. The first one is placed just before the QStringList::last call, while the second one (the one at the closing brace) is after the stack's unwound.

                              Read and abide by the Qt Code of Conduct

                              1 Reply Last reply
                              0
                              • JonBJ Online
                                JonBJ Online
                                JonB
                                wrote on last edited by JonB
                                #15

                                When you "step over" the str = assignment statement, it executes the code for that line plus the unwind which follows it. Are you saying the breakpoint on the } is supposed to be before the unwind, is that the point?

                                kshegunovK 1 Reply Last reply
                                0
                                • JonBJ JonB

                                  When you "step over" the str = assignment statement, it executes the code for that line plus the unwind which follows it. Are you saying the breakpoint on the } is supposed to be before the unwind, is that the point?

                                  kshegunovK Offline
                                  kshegunovK Offline
                                  kshegunov
                                  Moderators
                                  wrote on last edited by
                                  #16

                                  @JNBarchan said in Debug issue FYI:

                                  Are you saying the breakpoint on the } is supposed to before the unwind, is that the point?

                                  I'm saying that, since the breakpoint that is at } is after the stack unwinding you won't get to see what was in the QString object in the debugger's auto/watch pane when the debugger actually stops at the breakpoint. That's why introducing a dummy statement after QString str = list.last() can be used to break before the stack's been unwound.

                                  Read and abide by the Qt Code of Conduct

                                  JonBJ 1 Reply Last reply
                                  0
                                  • kshegunovK kshegunov

                                    @JNBarchan said in Debug issue FYI:

                                    Are you saying the breakpoint on the } is supposed to before the unwind, is that the point?

                                    I'm saying that, since the breakpoint that is at } is after the stack unwinding you won't get to see what was in the QString object in the debugger's auto/watch pane when the debugger actually stops at the breakpoint. That's why introducing a dummy statement after QString str = list.last() can be used to break before the stack's been unwound.

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

                                    @kshegunov
                                    LOL, yes, that's just why I said I often put in a final statement like str += "" (or any other statement) when debugging.
                                    I thought the debate was over whether the debugger is OK to choose to put the bp there or whether it should put it before the stack unwind.

                                    kshegunovK 1 Reply Last reply
                                    0
                                    • JonBJ JonB

                                      @kshegunov
                                      LOL, yes, that's just why I said I often put in a final statement like str += "" (or any other statement) when debugging.
                                      I thought the debate was over whether the debugger is OK to choose to put the bp there or whether it should put it before the stack unwind.

                                      kshegunovK Offline
                                      kshegunovK Offline
                                      kshegunov
                                      Moderators
                                      wrote on last edited by
                                      #18

                                      @JNBarchan said in Debug issue FYI:

                                      I thought the debate was over whether the debugger is OK to choose to put the bp there or whether it should put it before the stack unwind.

                                      This I don't know for sure, as indicated before. It may be considered a bug, it may be a feature. In any case my "main" point is that this isn't due to the compiler optimizing stuff, but just a peculiarity of the debugger/Qt Creator's debug helpers.

                                      Read and abide by the Qt Code of Conduct

                                      JonBJ 1 Reply Last reply
                                      1
                                      • kshegunovK kshegunov

                                        @JNBarchan said in Debug issue FYI:

                                        I thought the debate was over whether the debugger is OK to choose to put the bp there or whether it should put it before the stack unwind.

                                        This I don't know for sure, as indicated before. It may be considered a bug, it may be a feature. In any case my "main" point is that this isn't due to the compiler optimizing stuff, but just a peculiarity of the debugger/Qt Creator's debug helpers.

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

                                        @kshegunov
                                        OK, I agree. It was an interesting conversation anyway :)

                                        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