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. connect cause exception triggered (Beginner)
Forum Updated to NodeBB v4.3 + New Features

connect cause exception triggered (Beginner)

Scheduled Pinned Locked Moved Solved General and Desktop
26 Posts 4 Posters 9.3k Views 1 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.
  • VRoninV VRonin

    @jsulm I'm really confused now as I tested it and this code works 100% fine, even with [&]. how can it be?!

    #include <QCoreApplication>
    #include<QDebug>
    #include <QTimer>
    
    
    int main(int argc, char *argv[]) {
        QCoreApplication appl(argc,argv);
        QTimer mainTimer;
        mainTimer.setSingleShot(true);
        {
            QString* myString=nullptr;
            myString=new QString("A Message");
            QObject::connect(&mainTimer,&QTimer::timeout,[&](){qDebug() << *myString;});
            QObject::connect(&mainTimer,&QTimer::timeout,[=](){qDebug() << *myString;});
            // Memory leak!
        }
    
        mainTimer.start(100);
        return appl.exec();
    }
    
    

    EDIT:
    Using MSVC2013 on Windows

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

    @VRonin said:

    QObject::connect(&mainTimer,&QTimer::timeout,[&](){qDebug() << *myString;});
    

    What about:

    QObject::connect(&mainTimer,&QTimer::timeout,[&](){myString = nullptr;});
    

    You're capturing QString*, so you'd end up with: QString*& but you don't modify the string pointer, rather you dereference the object it's pointing to, so you'd try to output a QString & with QDebug. Also probably your compiler somewhat lax. :)

    PS.
    Well that's really disturbing ... I don't get any errors either. The memory will silently be overwritten. (g++ on Linux)

    Read and abide by the Qt Code of Conduct

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #17

      second test:

      #include <QCoreApplication>
      #include <QDebug>
      #include <QTimer>
      #include <QPointer>
      
      int main(int argc, char *argv[]) {
          QCoreApplication appl(argc,argv);
          QTimer mainTimer;
          mainTimer.setSingleShot(true);
          {
              QPointer<QObject> mybj;
              mybj =new QObject();
              mybj->setObjectName("A Message");
              QObject::connect(&mainTimer,&QTimer::timeout,[&](){qDebug() << mybj->objectName(); mybj->setObjectName("Foo"); qDebug() << mybj->objectName();});
              QObject::connect(&mainTimer,&QTimer::timeout,[=](){qDebug() << mybj->objectName(); mybj->setObjectName("Bar"); qDebug() << mybj->objectName();});
              // Memory leak!
          }
          {
              QString testString("Occuppy Stack");
          }
          mainTimer.start(100);
          return appl.exec();
      }
      
      

      Still working correctly. Notice how the first output of the [=] lambda is Foo. HOW?!

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      DumaPlusPlusD kshegunovK 2 Replies Last reply
      0
      • VRoninV VRonin

        second test:

        #include <QCoreApplication>
        #include <QDebug>
        #include <QTimer>
        #include <QPointer>
        
        int main(int argc, char *argv[]) {
            QCoreApplication appl(argc,argv);
            QTimer mainTimer;
            mainTimer.setSingleShot(true);
            {
                QPointer<QObject> mybj;
                mybj =new QObject();
                mybj->setObjectName("A Message");
                QObject::connect(&mainTimer,&QTimer::timeout,[&](){qDebug() << mybj->objectName(); mybj->setObjectName("Foo"); qDebug() << mybj->objectName();});
                QObject::connect(&mainTimer,&QTimer::timeout,[=](){qDebug() << mybj->objectName(); mybj->setObjectName("Bar"); qDebug() << mybj->objectName();});
                // Memory leak!
            }
            {
                QString testString("Occuppy Stack");
            }
            mainTimer.start(100);
            return appl.exec();
        }
        
        

        Still working correctly. Notice how the first output of the [=] lambda is Foo. HOW?!

        DumaPlusPlusD Offline
        DumaPlusPlusD Offline
        DumaPlusPlus
        wrote on last edited by DumaPlusPlus
        #18

        @VRonin said:

        second test:

                QObject::connect(&mainTimer,&QTimer::timeout,[&](){qDebug() << mybj->objectName(); mybj->setObjectName("Foo"); qDebug() << mybj->objectName();});
                QObject::connect(&mainTimer,&QTimer::timeout,[=](){qDebug() << mybj->objectName(); mybj->setObjectName("Bar"); qDebug() << mybj->objectName();});
        
        
        Still working correctly. Notice how the first output of the [=] lambda is Foo. HOW?!
        

        should be that?
        passing by value copy the pointer so you point to objname with modified name...right?

        VRoninV 1 Reply Last reply
        0
        • DumaPlusPlusD DumaPlusPlus

          @VRonin said:

          second test:

                  QObject::connect(&mainTimer,&QTimer::timeout,[&](){qDebug() << mybj->objectName(); mybj->setObjectName("Foo"); qDebug() << mybj->objectName();});
                  QObject::connect(&mainTimer,&QTimer::timeout,[=](){qDebug() << mybj->objectName(); mybj->setObjectName("Bar"); qDebug() << mybj->objectName();});
          
          
          Still working correctly. Notice how the first output of the [=] lambda is Foo. HOW?!
          

          should be that?
          passing by value copy the pointer so you point to objname with modified name...right?

          VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by VRonin
          #19

          @DumaPlusPlus The first lambda should never be executed at the creation of the second one. then when the timer times out I was expecting the first to crash or operate on invalid memory and the second to print

          A Message
          Bar
          

          While it looks like the lambda with [&] behaves exactly as the one with [=]

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          0
          • VRoninV VRonin

            second test:

            #include <QCoreApplication>
            #include <QDebug>
            #include <QTimer>
            #include <QPointer>
            
            int main(int argc, char *argv[]) {
                QCoreApplication appl(argc,argv);
                QTimer mainTimer;
                mainTimer.setSingleShot(true);
                {
                    QPointer<QObject> mybj;
                    mybj =new QObject();
                    mybj->setObjectName("A Message");
                    QObject::connect(&mainTimer,&QTimer::timeout,[&](){qDebug() << mybj->objectName(); mybj->setObjectName("Foo"); qDebug() << mybj->objectName();});
                    QObject::connect(&mainTimer,&QTimer::timeout,[=](){qDebug() << mybj->objectName(); mybj->setObjectName("Bar"); qDebug() << mybj->objectName();});
                    // Memory leak!
                }
                {
                    QString testString("Occuppy Stack");
                }
                mainTimer.start(100);
                return appl.exec();
            }
            
            

            Still working correctly. Notice how the first output of the [=] lambda is Foo. HOW?!

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

            @VRonin

            If I haven't missed anything. my g++ doesn't open a new stack frame when it sees: { }. So in your examples (which I used) all is flat, thus myString is in main()'s stack frame, which means it doesn't go out of scope (i.e. it's not pop-ed from the stack), which ultimately means that the lambda capture is valid.

            Here's what I have for main() from your QString test case:

            # Sets up main()'s stack
            0x400fc2                   55                                push   %rbp
            0x400fc3  <+0x0001>        48 89 e5                          mov    %rsp,%rbp
            ...
            0x400fcf  <+0x000d>        48 83 ec 78                       sub    $0x78,%rsp
            ...
            # mainTimer.setSingleShot(true);
            0x401010  <+0x004e>        48 8d 45 80                       lea    -0x80(%rbp),%rax
            0x401014  <+0x0052>        be 01 00 00 00                    mov    $0x1,%esi
            0x401019  <+0x0057>        48 89 c7                          mov    %rax,%rdi
            0x40101c  <+0x005a>        e8 59 08 00 00                    callq  0x40187a <QTimer::setSingleShot(bool)>
            # QString * myString = nullptr;
            0x401021  <+0x005f>        48 c7 85 78 ff ff ff 00 00 00 00  movq   $0x0,-0x88(%rbp)
            # No stack frame was opened as one'd expect from a block
            ...
            # main()'s stack's being unwound
            0x40113c  <+0x017a>        48 83 c4 78                       add    $0x78,%rsp
            ...
            0x401149  <+0x0187>        5d                                pop    %rbp
            # And that was all folks, thanks for playing
            0x40114a  <+0x0188>        c3                                retq         
            

            As for the lambda, it doesn't make any checks. It just stores the captured address (the reference) and ultimately dereferences it when it's executed:

            ...
            # qDebug() << *myString;
            0x400ec3  <+0x000d>        48 8b 45 b8           mov    -0x48(%rbp),%rax    # Load QString *& from the base pointer
            0x400ec7  <+0x0011>        48 8b 00              mov    (%rax),%rax         # Dereference once (strip &)
            0x400eca  <+0x0014>        48 8b 18              mov    (%rax),%rbx         # Dereference second time i.e. (*myString)
            

            So I hope this explains how and why.

            Kind regards.

            Read and abide by the Qt Code of Conduct

            VRoninV 1 Reply Last reply
            1
            • kshegunovK kshegunov

              @VRonin

              If I haven't missed anything. my g++ doesn't open a new stack frame when it sees: { }. So in your examples (which I used) all is flat, thus myString is in main()'s stack frame, which means it doesn't go out of scope (i.e. it's not pop-ed from the stack), which ultimately means that the lambda capture is valid.

              Here's what I have for main() from your QString test case:

              # Sets up main()'s stack
              0x400fc2                   55                                push   %rbp
              0x400fc3  <+0x0001>        48 89 e5                          mov    %rsp,%rbp
              ...
              0x400fcf  <+0x000d>        48 83 ec 78                       sub    $0x78,%rsp
              ...
              # mainTimer.setSingleShot(true);
              0x401010  <+0x004e>        48 8d 45 80                       lea    -0x80(%rbp),%rax
              0x401014  <+0x0052>        be 01 00 00 00                    mov    $0x1,%esi
              0x401019  <+0x0057>        48 89 c7                          mov    %rax,%rdi
              0x40101c  <+0x005a>        e8 59 08 00 00                    callq  0x40187a <QTimer::setSingleShot(bool)>
              # QString * myString = nullptr;
              0x401021  <+0x005f>        48 c7 85 78 ff ff ff 00 00 00 00  movq   $0x0,-0x88(%rbp)
              # No stack frame was opened as one'd expect from a block
              ...
              # main()'s stack's being unwound
              0x40113c  <+0x017a>        48 83 c4 78                       add    $0x78,%rsp
              ...
              0x401149  <+0x0187>        5d                                pop    %rbp
              # And that was all folks, thanks for playing
              0x40114a  <+0x0188>        c3                                retq         
              

              As for the lambda, it doesn't make any checks. It just stores the captured address (the reference) and ultimately dereferences it when it's executed:

              ...
              # qDebug() << *myString;
              0x400ec3  <+0x000d>        48 8b 45 b8           mov    -0x48(%rbp),%rax    # Load QString *& from the base pointer
              0x400ec7  <+0x0011>        48 8b 00              mov    (%rax),%rax         # Dereference once (strip &)
              0x400eca  <+0x0014>        48 8b 18              mov    (%rax),%rbx         # Dereference second time i.e. (*myString)
              

              So I hope this explains how and why.

              Kind regards.

              VRoninV Offline
              VRoninV Offline
              VRonin
              wrote on last edited by
              #21

              Thanks @kshegunov now it make sense, it was just the compiler (I use MSVC btw) optimizing.
              This behaves as expected.

              #include <QCoreApplication>
              #include<QDebug>
              #include <QTimer>
              
              void makeConnections(QTimer* mainTimer ){
                  QString* myString=nullptr;
                  myString=new QString("A Message");
                  QObject::connect(mainTimer,&QTimer::timeout,[&](){qDebug() << *myString;});
                  QObject::connect(mainTimer,&QTimer::timeout,[=](){qDebug() << *myString;});
              }
              
              int main(int argc, char *argv[]) {
                  QCoreApplication appl(argc,argv);
                  QTimer mainTimer;
                  mainTimer.setSingleShot(true);
                  makeConnections(&mainTimer);
              
                  mainTimer.start(100);
                  return appl.exec();
              }
              
              

              I marked my previous post where I was wrong and the final answer to the topic is use [=] in the lambda instead of [&]

              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
              ~Napoleon Bonaparte

              On a crusade to banish setIndexWidget() from the holy land of Qt

              kshegunovK 1 Reply Last reply
              0
              • VRoninV VRonin

                Thanks @kshegunov now it make sense, it was just the compiler (I use MSVC btw) optimizing.
                This behaves as expected.

                #include <QCoreApplication>
                #include<QDebug>
                #include <QTimer>
                
                void makeConnections(QTimer* mainTimer ){
                    QString* myString=nullptr;
                    myString=new QString("A Message");
                    QObject::connect(mainTimer,&QTimer::timeout,[&](){qDebug() << *myString;});
                    QObject::connect(mainTimer,&QTimer::timeout,[=](){qDebug() << *myString;});
                }
                
                int main(int argc, char *argv[]) {
                    QCoreApplication appl(argc,argv);
                    QTimer mainTimer;
                    mainTimer.setSingleShot(true);
                    makeConnections(&mainTimer);
                
                    mainTimer.start(100);
                    return appl.exec();
                }
                
                

                I marked my previous post where I was wrong and the final answer to the topic is use [=] in the lambda instead of [&]

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

                @VRonin

                Thanks @kshegunov now it make sense, it was just the compiler (I use MSVC btw) optimizing.

                No problem. Yes the compiler was an issue apparently, although that's some strange optimization made. Especially if you take into account we're running in debug mode, two different compilers no less. But even in release mode I'd venture to say one doesn't expect a block to just be ignored ... at least I don't.

                This behaves as expected.

                Meaning it crashes at the appropriate place? :)

                Read and abide by the Qt Code of Conduct

                VRoninV 1 Reply Last reply
                0
                • kshegunovK kshegunov

                  @VRonin

                  Thanks @kshegunov now it make sense, it was just the compiler (I use MSVC btw) optimizing.

                  No problem. Yes the compiler was an issue apparently, although that's some strange optimization made. Especially if you take into account we're running in debug mode, two different compilers no less. But even in release mode I'd venture to say one doesn't expect a block to just be ignored ... at least I don't.

                  This behaves as expected.

                  Meaning it crashes at the appropriate place? :)

                  VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by
                  #23

                  @kshegunov said:

                  Meaning it crashes at the appropriate place? :)

                  Even a crash sometimes is expected behaviour ;)

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  1 Reply Last reply
                  1
                  • DumaPlusPlusD Offline
                    DumaPlusPlusD Offline
                    DumaPlusPlus
                    wrote on last edited by
                    #24

                    wow very good thread i wish i will be professional like you

                    kshegunovK 1 Reply Last reply
                    0
                    • DumaPlusPlusD DumaPlusPlus

                      wow very good thread i wish i will be professional like you

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

                      @DumaPlusPlus
                      It's only matter of experience, so just be patient. And funnily enough currently I don't work as a programmer, so I'm actually falling in the category of amateur, or at least hobbyist. ;)

                      @jsulm
                      Out of curiosity, what compiler are you running?

                      Read and abide by the Qt Code of Conduct

                      jsulmJ 1 Reply Last reply
                      1
                      • kshegunovK kshegunov

                        @DumaPlusPlus
                        It's only matter of experience, so just be patient. And funnily enough currently I don't work as a programmer, so I'm actually falling in the category of amateur, or at least hobbyist. ;)

                        @jsulm
                        Out of curiosity, what compiler are you running?

                        jsulmJ Offline
                        jsulmJ Offline
                        jsulm
                        Lifetime Qt Champion
                        wrote on last edited by
                        #26

                        @kshegunov MinGW 5.3.0 32bit on Windows 7.

                        https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        0

                        • Login

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