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 with lambda and capture by reference causes segmentation fault
Forum Updated to NodeBB v4.3 + New Features

Connect with lambda and capture by reference causes segmentation fault

Scheduled Pinned Locked Moved Solved General and Desktop
3 Posts 2 Posters 1.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.
  • V Offline
    V Offline
    VictorLamoine
    wrote on last edited by VictorLamoine
    #1

    Hi,

    I'm wondering why capturing by reference in a connect lambda causes a segmentation fault.

    CMakeLists.txt

    cmake_minimum_required(VERSION 3.5)
    project(test_qt LANGUAGES CXX)
    add_compile_options(-Wall -Wextra)
    set(CMAKE_CXX_STANDARD 14)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    set(CMAKE_AUTOMOC ON)
    find_package(Qt5 COMPONENTS Widgets REQUIRED)
    
    add_executable(
      ${PROJECT_NAME}
      mainwindow.hpp
      mainwindow.cpp
      main.cpp
    )
    target_link_libraries(
      ${PROJECT_NAME}
      Qt5::Widgets
    )
    

    main.cpp

    #include "mainwindow.hpp"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
      QApplication a(argc, argv);
      MainWindow w;
      w.show();
      return a.exec();
    }
    

    mainwindow.hpp

    #ifndef MAINWINDOW_HPP
    #define MAINWINDOW_HPP
    
    #include <QLabel>
    #include <QMainWindow>
    #include <QPushButton>
    #include <QVBoxLayout>
    
    class MainWindow : public QMainWindow
    {
      Q_OBJECT
    
    public:
      MainWindow(QWidget *parent = nullptr);
      ~MainWindow();
    };
    
    #endif
    

    mainwindow.cpp

    #include "mainwindow.hpp"
    
    MainWindow::MainWindow(QWidget *parent)
      : QMainWindow(parent)
    {
      QWidget *widget(new QWidget);
      setCentralWidget(widget);
      QVBoxLayout *layout(new QVBoxLayout(widget));
    
      QLabel *label(new QLabel("QLabel"));
      QPushButton *change_label(new QPushButton("Change label"));
    
      layout->addWidget(label);
      layout->addWidget(change_label);
    
      connect(change_label, &QPushButton::clicked, this, [&]() // FIXME Capture by reference = crash, capture by copy is ok!
      {
        label->setText("Hello");
      });
    }
    
    MainWindow::~MainWindow()
    {
    }
    

    Is it explicitly forbidden in Qt to capture by reference in a connect lambda?

    • Kubuntu 18.04
    • Qt 5.9.5
    • gcc 9.3.0
    • CMake 3.19.3

    gdb backtrace:

    (gdb) run
    Starting program: /home/victor/Documents/code/tests/qt/build/test_qt test_qt
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    [New Thread 0x7fffebd72700 (LWP 31414)]
    [New Thread 0x7fffdc88a700 (LWP 31415)]
    
    Thread 1 "test_qt" received signal SIGSEGV, Segmentation fault.
    0x00007ffff6f67b78 in operator==(QString const&, QString const&) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
    (gdb) bt
    #0    0x00007ffff6f67b78 in operator==(QString const&, QString const&) + 0x8 () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
    #1    0x00007ffff78183f7 in QLabel::setText(QString const&) + 0x37 () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #2    0x0000555555556964 in MainWindow::<lambda()>::operator()(void) const (__closure=0x5555558497d0)
                             at /home/victor/code/tests/qt/src/mainwindow.cpp:18
    #3    0x0000555555556eee in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, MainWindow::MainWindow(QWidget*)::<lambda()> >::call(MainWindow::<lambda()> &, void **) (f=@0x5555558497d0, arg=0x7fffffffcd50)
                             at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h:130
    #4    0x0000555555556ec0 in QtPrivate::Functor<MainWindow::MainWindow(QWidget*)::<lambda()>, 0>::call<QtPrivate::List<>, void>(MainWindow::<lambda()> &, void *, void **) (f=@0x5555558497d0, arg=0x7fffffffcd50)
                             at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h:240
    #5    0x0000555555556e8e in QtPrivate::QFunctorSlotObject<MainWindow::MainWindow(QWidget*)::<lambda()>, 0, QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase *, QObject *, void **, bool *) (which=1, this_=0x5555558497c0, r=0x7fffffffda30, a=0x7fffffffcd50, ret=0x0)
                             at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h:168
    #6    0x00007ffff70fa66f in QMetaObject::activate(QObject*, int, int, void**) + 0x97f () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
    #7    0x00007ffff77d1ba2 in QAbstractButton::clicked(bool) + 0x42 () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #8    0x00007ffff77d1dba in No symbol matches 0x00007ffff77d1dba. () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #9    0x00007ffff77d319a in No symbol matches 0x00007ffff77d319a. () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #10   0x00007ffff77d338d in QAbstractButton::mouseReleaseEvent(QMouseEvent*) + 0xfd () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #11   0x00007ffff771f048 in QWidget::event(QEvent*) + 0x1f8 () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #12   0x00007ffff76e083c in QApplicationPrivate::notify_helper(QObject*, QEvent*) + 0x9c () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #13   0x00007ffff76e865f in QApplication::notify(QObject*, QEvent*) + 0x7ff () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #14   0x00007ffff70cb8d8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) + 0x118 () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
    #15   0x00007ffff76e7632 in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool) + 0x1d2 ()
                             at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #16   0x00007ffff773a16b in No symbol matches 0x00007ffff773a16b. () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #17   0x00007ffff773c7da in No symbol matches 0x00007ffff773c7da. () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #18   0x00007ffff76e083c in QApplicationPrivate::notify_helper(QObject*, QEvent*) + 0x9c () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #19   0x00007ffff76e8104 in QApplication::notify(QObject*, QEvent*) + 0x2a4 () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
    #20   0x00007ffff70cb8d8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) + 0x118 () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
    #21   0x00007ffff5dfc583 in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) + 0x6f3 ()
                             at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
    #22   0x00007ffff5dfe055 in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) + 0x135 ()
                             at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
    #23   0x00007ffff5dd52eb in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 0xab ()
                             at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
    #24   0x00007fffefe55260 in No symbol matches 0x00007fffefe55260. () at /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5
    #25   0x00007ffff45e8417 in g_main_context_dispatch + 0x2e7 () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
    #26   0x00007ffff45e8650 in No symbol matches 0x00007ffff45e8650. () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
    #27   0x00007ffff45e86dc in g_main_context_iteration + 0x2c () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
    #28   0x00007ffff712488f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 0x5f ()
                             at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
    #29   0x00007ffff70c990a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 0x13a () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
    #30   0x00007ffff70d29b4 in QCoreApplication::exec() + 0x94 () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
    #31   0x0000555555557252 in main(int, char**) (argc=2, argv=0x7fffffffdb68) at /home/victor/code/tests/qt/src/main.cpp:9
    
    

    Bye

    raven-worxR 1 Reply Last reply
    0
    • V VictorLamoine

      Hi,

      I'm wondering why capturing by reference in a connect lambda causes a segmentation fault.

      CMakeLists.txt

      cmake_minimum_required(VERSION 3.5)
      project(test_qt LANGUAGES CXX)
      add_compile_options(-Wall -Wextra)
      set(CMAKE_CXX_STANDARD 14)
      set(CMAKE_CXX_STANDARD_REQUIRED ON)
      
      set(CMAKE_AUTOMOC ON)
      find_package(Qt5 COMPONENTS Widgets REQUIRED)
      
      add_executable(
        ${PROJECT_NAME}
        mainwindow.hpp
        mainwindow.cpp
        main.cpp
      )
      target_link_libraries(
        ${PROJECT_NAME}
        Qt5::Widgets
      )
      

      main.cpp

      #include "mainwindow.hpp"
      #include <QApplication>
      
      int main(int argc, char *argv[])
      {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
        return a.exec();
      }
      

      mainwindow.hpp

      #ifndef MAINWINDOW_HPP
      #define MAINWINDOW_HPP
      
      #include <QLabel>
      #include <QMainWindow>
      #include <QPushButton>
      #include <QVBoxLayout>
      
      class MainWindow : public QMainWindow
      {
        Q_OBJECT
      
      public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
      };
      
      #endif
      

      mainwindow.cpp

      #include "mainwindow.hpp"
      
      MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
      {
        QWidget *widget(new QWidget);
        setCentralWidget(widget);
        QVBoxLayout *layout(new QVBoxLayout(widget));
      
        QLabel *label(new QLabel("QLabel"));
        QPushButton *change_label(new QPushButton("Change label"));
      
        layout->addWidget(label);
        layout->addWidget(change_label);
      
        connect(change_label, &QPushButton::clicked, this, [&]() // FIXME Capture by reference = crash, capture by copy is ok!
        {
          label->setText("Hello");
        });
      }
      
      MainWindow::~MainWindow()
      {
      }
      

      Is it explicitly forbidden in Qt to capture by reference in a connect lambda?

      • Kubuntu 18.04
      • Qt 5.9.5
      • gcc 9.3.0
      • CMake 3.19.3

      gdb backtrace:

      (gdb) run
      Starting program: /home/victor/Documents/code/tests/qt/build/test_qt test_qt
      [Thread debugging using libthread_db enabled]
      Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
      [New Thread 0x7fffebd72700 (LWP 31414)]
      [New Thread 0x7fffdc88a700 (LWP 31415)]
      
      Thread 1 "test_qt" received signal SIGSEGV, Segmentation fault.
      0x00007ffff6f67b78 in operator==(QString const&, QString const&) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
      (gdb) bt
      #0    0x00007ffff6f67b78 in operator==(QString const&, QString const&) + 0x8 () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
      #1    0x00007ffff78183f7 in QLabel::setText(QString const&) + 0x37 () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #2    0x0000555555556964 in MainWindow::<lambda()>::operator()(void) const (__closure=0x5555558497d0)
                               at /home/victor/code/tests/qt/src/mainwindow.cpp:18
      #3    0x0000555555556eee in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, MainWindow::MainWindow(QWidget*)::<lambda()> >::call(MainWindow::<lambda()> &, void **) (f=@0x5555558497d0, arg=0x7fffffffcd50)
                               at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h:130
      #4    0x0000555555556ec0 in QtPrivate::Functor<MainWindow::MainWindow(QWidget*)::<lambda()>, 0>::call<QtPrivate::List<>, void>(MainWindow::<lambda()> &, void *, void **) (f=@0x5555558497d0, arg=0x7fffffffcd50)
                               at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobjectdefs_impl.h:240
      #5    0x0000555555556e8e in QtPrivate::QFunctorSlotObject<MainWindow::MainWindow(QWidget*)::<lambda()>, 0, QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase *, QObject *, void **, bool *) (which=1, this_=0x5555558497c0, r=0x7fffffffda30, a=0x7fffffffcd50, ret=0x0)
                               at /usr/include/x86_64-linux-gnu/qt5/QtCore/qobject_impl.h:168
      #6    0x00007ffff70fa66f in QMetaObject::activate(QObject*, int, int, void**) + 0x97f () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
      #7    0x00007ffff77d1ba2 in QAbstractButton::clicked(bool) + 0x42 () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #8    0x00007ffff77d1dba in No symbol matches 0x00007ffff77d1dba. () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #9    0x00007ffff77d319a in No symbol matches 0x00007ffff77d319a. () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #10   0x00007ffff77d338d in QAbstractButton::mouseReleaseEvent(QMouseEvent*) + 0xfd () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #11   0x00007ffff771f048 in QWidget::event(QEvent*) + 0x1f8 () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #12   0x00007ffff76e083c in QApplicationPrivate::notify_helper(QObject*, QEvent*) + 0x9c () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #13   0x00007ffff76e865f in QApplication::notify(QObject*, QEvent*) + 0x7ff () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #14   0x00007ffff70cb8d8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) + 0x118 () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
      #15   0x00007ffff76e7632 in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool) + 0x1d2 ()
                               at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #16   0x00007ffff773a16b in No symbol matches 0x00007ffff773a16b. () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #17   0x00007ffff773c7da in No symbol matches 0x00007ffff773c7da. () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #18   0x00007ffff76e083c in QApplicationPrivate::notify_helper(QObject*, QEvent*) + 0x9c () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #19   0x00007ffff76e8104 in QApplication::notify(QObject*, QEvent*) + 0x2a4 () at /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
      #20   0x00007ffff70cb8d8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) + 0x118 () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
      #21   0x00007ffff5dfc583 in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) + 0x6f3 ()
                               at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
      #22   0x00007ffff5dfe055 in QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) + 0x135 ()
                               at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
      #23   0x00007ffff5dd52eb in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 0xab ()
                               at /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
      #24   0x00007fffefe55260 in No symbol matches 0x00007fffefe55260. () at /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5
      #25   0x00007ffff45e8417 in g_main_context_dispatch + 0x2e7 () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
      #26   0x00007ffff45e8650 in No symbol matches 0x00007ffff45e8650. () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
      #27   0x00007ffff45e86dc in g_main_context_iteration + 0x2c () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
      #28   0x00007ffff712488f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 0x5f ()
                               at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
      #29   0x00007ffff70c990a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 0x13a () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
      #30   0x00007ffff70d29b4 in QCoreApplication::exec() + 0x94 () at /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
      #31   0x0000555555557252 in main(int, char**) (argc=2, argv=0x7fffffffdb68) at /home/victor/code/tests/qt/src/main.cpp:9
      
      

      Bye

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by raven-worx
      #2

      @VictorLamoine
      i guess the reason for this behavior is that your label pointer variable is deleted when it goes out of scope.
      i am talking about the pointer variable holding the address, not the actual QLabel instance. If you capture it by value a new pointer variable lives inside the scope of your lambda.
      Btw. the default capture type is also by value not by reference.

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      7
      • V Offline
        V Offline
        VictorLamoine
        wrote on last edited by
        #3

        That's right!

        If instead the widgets are declared private in the class:

        class MainWindow : public QMainWindow
        {
          Q_OBJECT
        
        public:
          MainWindow(QWidget *parent = nullptr);
          ~MainWindow();
        
        private:
          QLabel *label_;
          QPushButton *change_label_;
        };
        

        Then using a connect / lambda with capture by reference works fine:

        MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent)
        {
          QWidget *widget(new QWidget);
          setCentralWidget(widget);
          QVBoxLayout *layout(new QVBoxLayout(widget));
        
          label_ = new QLabel("QLabel");
          change_label_ = new QPushButton("Change label");
        
          layout->addWidget(label_);
          layout->addWidget(change_label_);
        
          connect(change_label_, &QPushButton::clicked, this, [&]() // Capture by reference works!
          {
            label_->setText("Hello");
          });
        }
        

        The problem was indeed the scope of the variable.

        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