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
Qt 6.11 is out! See what's new in the release blog

Debug issue FYI

Scheduled Pinned Locked Moved Unsolved General and Desktop
19 Posts 5 Posters 3.8k 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 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 Offline
      JonBJ Offline
      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 Offline
          JonBJ Offline
          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 Offline
                JonBJ Offline
                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 Offline
                    JonBJ Offline
                    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 Offline
                        JonBJ Offline
                        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