crash desallocating local string when closing socket



  • Hi,
    I've a crash when I disconnect my socket in the handler of readyRead.
    I don't understand what is the problem.
    Here is my code:

    #include "monitorhandler.h"
    
    MonitorHandler::MonitorHandler(ushort aPort):
        iPort(aPort), iServer(Q_NULLPTR), iSocket(Q_NULLPTR), iLogPrefix("[MonitorHandler] ")
    {
    #ifdef LOG_CONSTRUCTORS
        _log("Constructor");
    #endif
    }
    
    MonitorHandler::~MonitorHandler(){
    #ifdef LOG_CONSTRUCTORS
        _log("Destructor");
    #endif
        delete iSocket;
        delete iServer;
    }
    
    bool MonitorHandler::startServer(){
        iServer = new QTcpServer();
    
        bool isAcceptingConnection = true;
        QString str;
        if (iServer->listen(QHostAddress::LocalHost, iPort)){
            str = "Monitoring Server listening locally on port ";
            connect(iServer, &QTcpServer::newConnection, this, &MonitorHandler::newConnection);
        } else {
            str = "Error: Monitoring Server can't listen locally on port ";
            isAcceptingConnection = false;
        }
        str += QString::number(iPort);
        _log(str);
    
        return isAcceptingConnection;
    }
    
    void MonitorHandler::newConnection(){
        QTcpSocket *sock = iServer->nextPendingConnection();
        if (iSocket != Q_NULLPTR){
            _log("Ignore Connection: Monitor Server has already a local connection...");
            sock->write("Already a connection in use...\n");
            sock->flush();
            delete sock;
        } else {
            iSocket = sock;
            _log("New Connection");
            iSocket->write("Hello\n");
            iSocket->flush();
            //    connect(iSocket, &QTcpSocket::error, this, &MonitorHandler::onErrors);
            connect(iSocket, SIGNAL(error(QAbstractSocket::SocketError)),
                    this, SLOT(onErrors(QAbstractSocket::SocketError)), Qt::QueuedConnection);
            connect(iSocket, &QTcpSocket::disconnected, this, &MonitorHandler::disconnected);
            connect(iSocket, &QTcpSocket::readyRead, this, &MonitorHandler::readyRead);
        }
    }
    
    void MonitorHandler::readyRead(){
        if(iSocket->canReadLine()){
            QByteArray line = iSocket->readLine();
    #ifdef LOG_MONITOR_DATA
            QString str("Data In: ");
            str += line;
            _log(str);
    #endif
            if(strcmp(line.constData(), "quit\r\n") == 0){
                iSocket->disconnectFromHost();
            } else {
                iSocket->write(line);
                iSocket->flush();
            }
        }
    }
    
    void MonitorHandler::disconnected(){
        _log("disconnected...");
    //    disconnect(iSocket, &QTcpSocket::readyRead, this, &MonitorHandler::readyRead);
        delete iSocket;
        iSocket = Q_NULLPTR;
    }
    
    void MonitorHandler::onErrors(QAbstractSocket::SocketError){
        QString err("Error Socket: ");
        err += iSocket->errorString();
        _log(err);
    
        iSocket->disconnectFromHost();
    }
    

    It crashes when it tries to desallocate the QString I'm using for my log:

    #ifdef LOG_MONITOR_DATA
            QString str("Data In: ");
            str += line;
            _log(str);
    #endif
    

    If I don't use this log, everything works fine... What is the issue?

    Here is the full backtrace:

    
    Thread 4 (Thread 0xb3dffb40 (LWP 4241)):
    #0  0xb77c2d40 in __kernel_vsyscall ()
    No symbol table info available.
    #1  0xb6d7f307 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
            resultvar = <optimized out>
            resultvar = <optimized out>
            pid = -1225822208
            selftid = 4241
    #2  0xb6d809c3 in __GI_abort () at abort.c:89
            save_stage = 2
            act = {__sigaction_handler = {sa_handler = 0xb34027d8, sa_sigaction = 0xb34027d8}, sa_mask = {__val = {1, 3067887109, 3007327328, 3007327328, 0, 3069869672, 0, 3073445094, 3076392512, 3070529536, 3007327008, 3069869654, 3007315984, 3069869736, 3007361560, 3073445222, 1, 3076392512, 3007327328, 3007327328, 3076407524, 3072516644, 3007327328, 1, 3076966873, 3070529536, 3007327328, 3007327328, 3076407524, 0, 3, 4096}}, sa_flags = -1226612904, sa_restorer = 0x1000}
            sigs = {__val = {32, 0 <repeats 31 times>}}
    #3  0xb6dbd6f8 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0xb6eb365c "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
            ap = <optimized out>
            fd = 10
            on_2 = <optimized out>
            list = <optimized out>
            nlist = <optimized out>
            cp = <optimized out>
            written = <optimized out>
    #4  0xb6dc376a in malloc_printerr (action=<optimized out>, str=0xb6eaf138 "corrupted double-linked list", ptr=0xb3402f98) at malloc.c:4996
            buf = "b3402f98"
            cp = <optimized out>
    #5  0xb6dc39f4 in malloc_consolidate (av=0xb3400010) at malloc.c:4157
            fb = 0xb3400018
            maxfb = 0xb340003c
            p = 0xb3402f98
            nextp = 0x0
            unsorted_bin = 0xb3400040
            first_unsorted = <optimized out>
            nextchunk = 0xb340b020
            size = 32904
            nextsize = 56
            prevsize = <optimized out>
            nextinuse = <optimized out>
            bck = <optimized out>
            fwd = <optimized out>
            __func__ = "malloc_consolidate"
    #6  0xb6dc436b in _int_free (av=0xb3400010, p=<optimized out>, have_lock=0) at malloc.c:4057
            size = 73152
            fb = <optimized out>
            nextchunk = <optimized out>
            nextsize = <optimized out>
            nextinuse = <optimized out>
            prevsize = <optimized out>
            bck = <optimized out>
            fwd = <optimized out>
            errstr = 0x0
            locked = 1
            __func__ = "_int_free"
    #7  0xb7128476 in QArrayData::deallocate(QArrayData*, unsigned int, unsigned int) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #8  0x0804e257 in QTypedArrayData<unsigned short>::deallocate (data=0xb340f248) at /opt/Qt5.5.1/5.5/gcc/include/QtCore/qarraydata.h:222
    No locals.
    #9  0x0804e1dc in QString::~QString (this=0xb3dfee28, __in_chrg=<optimized out>) at /opt/Qt5.5.1/5.5/gcc/include/QtCore/qstring.h:1053
    No locals.
    #10 0x0808ef86 in MonitorHandler::readyRead (this=0x84c13f8) at ../nntpProxyQT/monitorhandler.cpp:63
            line = {static MaxSize = 1073741808, d = 0xb340f220}
            str = {static null = {<No data fields>}, d = 0xb340f248}
    #11 0x0808f542 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (MonitorHandler::*)()>::call(void (MonitorHandler::*)(), MonitorHandler*, void**) (f=(void (MonitorHandler::*)(MonitorHandler * const)) 0x808ee7a <MonitorHandler::readyRead()>, o=0x84c13f8, arg=0xb3dfef1c) at /opt/Qt5.5.1/5.5/gcc/include/QtCore/qobjectdefs_impl.h:501
    No locals.
    #12 0x0808f4f3 in QtPrivate::FunctionPointer<void (MonitorHandler::*)()>::call<QtPrivate::List<>, void>(void (MonitorHandler::*)(), MonitorHandler*, void**) (f=(void (MonitorHandler::*)(MonitorHandler * const)) 0x808ee7a <MonitorHandler::readyRead()>, o=0x84c13f8, arg=0xb3dfef1c) at /opt/Qt5.5.1/5.5/gcc/include/QtCore/qobjectdefs_impl.h:520
    No locals.
    #13 0x0808f48a in QtPrivate::QSlotObject<void (MonitorHandler::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (which=1, this_=0xb340b0b0, r=0x84c13f8, a=0xb3dfef1c, ret=0x0) at /opt/Qt5.5.1/5.5/gcc/include/QtCore/qobject_impl.h:143
    No locals.
    #14 0xb7339598 in QMetaObject::activate(QObject*, int, int, void**) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #15 0xb733a12d in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #16 0xb73b80e2 in QIODevice::readyRead() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #17 0xb76ef030 in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Network.so.5
    No symbol table info available.
    #18 0xb76e265a in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Network.so.5
    No symbol table info available.
    #19 0xb76fcc1f in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Network.so.5
    No symbol table info available.
    #20 0xb730a5fc in QCoreApplicationPrivate::notify_helper(QObject*, QEvent*) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #21 0xb730a760 in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #22 0xb7362425 in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #23 0xb5011da4 in g_main_context_dispatch () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #24 0xb50120c9 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #25 0xb5012196 in g_main_context_iteration () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #26 0xb7361dbc in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #27 0xb7307d13 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #28 0xb730818a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #29 0xb7121c85 in QThread::exec() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #30 0xb7121d58 in QThread::run() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #31 0xb7126f60 in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #32 0xb7057efb in start_thread (arg=0xb3dffb40) at pthread_create.c:309
            __res = <optimized out>
            pd = 0xb3dffb40
            now = <optimized out>
            unwind_buf = {cancel_jmp_buf = {{jmp_buf = {-1224302592, -1277166784, 4001536, -1277168600, 2084264619, -920638814}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
            not_first_call = <optimized out>
            pagesize_m1 = <optimized out>
            sp = <optimized out>
            freesize = <optimized out>
            __PRETTY_FUNCTION__ = "start_thread"
    #33 0xb6e3a62e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:129
    No locals.
    
    Thread 3 (Thread 0xb47b1b40 (LWP 4238)):
    #0  0xb77c2d40 in __kernel_vsyscall ()
    No symbol table info available.
    #1  0xb705c015 in pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/pthread_cond_timedwait.S:245
    No locals.
    #2  0xb7127ebd in QWaitCondition::wait(QMutex*, unsigned long) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #3  0xb7123f1a in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #4  0xb7126f60 in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #5  0xb7057efb in start_thread (arg=0xb47b1b40) at pthread_create.c:309
            __res = <optimized out>
            pd = 0xb47b1b40
            now = <optimized out>
            unwind_buf = {cancel_jmp_buf = {{jmp_buf = {-1224302592, -1267000512, 4001536, -1267002328, 905665188, -920638814}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
            not_first_call = <optimized out>
            pagesize_m1 = <optimized out>
            sp = <optimized out>
            freesize = <optimized out>
            __PRETTY_FUNCTION__ = "start_thread"
    #6  0xb6e3a62e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:129
    No locals.
    
    Thread 1 (Thread 0xb4f57700 (LWP 4229)):
    #0  0xb77c2d40 in __kernel_vsyscall ()
    No symbol table info available.
    #1  0xb6e2fdeb in poll () at ../sysdeps/unix/syscall-template.S:81
    No locals.
    #2  0xb50210b0 in g_poll () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #3  0xb5012054 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #4  0xb5012196 in g_main_context_iteration () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #5  0xb7361dbc in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #6  0xb7307d13 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #7  0xb730818a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #8  0xb731028a in QCoreApplication::exec() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #9  0x0804e02d in main (argc=1, argv=0xbf81fa04) at ../nntpProxyQT/main.cpp:45
            app = <incomplete type>
            theProxy = 0x83f20e8
            configFile = 0x0
    

    This server is running in its own Thread.

            iMonitorThread = new QThread();
            iMonitorThread->start();
    
            iMonitorHandler = new MonitorHandler();
            connect(this, &Proxy::startMonitoring, iMonitorHandler, &MonitorHandler::startServer);
            iMonitorHandler->moveToThread(iMonitorThread);
    
            emit startMonitoring();
    

    Any idea what I'm doing wrong? I'd like to be able to use my log...


  • Qt Champions 2016

    Hello,
    Is _log() used elsewhere in the code? Is it tread-safe? Could you share its implementation?



  • well yeah my _log function is thread safe. I'm using it in other parts of the project (multi threaded) without any issue...

    void MonitorHandler::_log(const QString & aMessage) const {
         Proxy::log(iLogPrefix, aMessage);
    }
    
    void Proxy::log(const QString & aClassPrefix, const QString &aMessage){
        QString str(aClassPrefix);
        str.append(aMessage);
        *sLogMain << str;
    }
    
    Log & Log::operator<< (const QString & aStr){
        QMutexLocker lock(&iMutex);
        writeLinePrefix();
        iStream << aStr << "\n";
        iStream.flush();
        return *this;
    }
    

    iStream being a QTextStream that is attached to an open QFile (iStream.setDevice(&iFile))



  • I've just tried to remove the call of my _log function.
    I've replaced it with a qDebug call.

    Still crashing but the backtrace is a bit different:

    Thread 4 (Thread 0xb3df2b40 (LWP 5066)):
    #0  0xb7719d40 in __kernel_vsyscall ()
    No symbol table info available.
    #1  0xb6cd6307 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
            resultvar = <optimized out>
            resultvar = <optimized out>
            pid = -1226514432
            selftid = 5066
    #2  0xb6cd79c3 in __GI_abort () at abort.c:89
            save_stage = 2
            act = {__sigaction_handler = {sa_handler = 0xb7267ce6 <QEvent::~QEvent()+6>, sa_sigaction = 0xb7267ce6 <QEvent::~QEvent()+6>}, sa_mask = {__val = {3075700288, 3069837312, 3007327008, 3069177430, 3007315984, 3069177512, 3007361808, 3072752998, 1, 3075700288, 3007327328, 3007327328, 3075715212, 3071824420, 3007327328, 1, 3076274649, 3069837312, 3007327328, 3007327328, 3075715212, 3069177448, 0, 3007327328, 3075715212, 3076822231, 3076822183, 3069177430, 3077657284, 0, 3, 4096}}, sa_flags = -1227305128, sa_restorer = 0x1000}
            sigs = {__val = {32, 0 <repeats 31 times>}}
    #3  0xb6d146f8 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0xb6e0a65c "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
            ap = <optimized out>
            fd = 10
            on_2 = <optimized out>
            list = <optimized out>
            nlist = <optimized out>
            cp = <optimized out>
            written = <optimized out>
    #4  0xb6d1a76a in malloc_printerr (action=<optimized out>, str=0xb6e06138 "corrupted double-linked list", ptr=0xb340b298) at malloc.c:4996
            buf = "b340b298"
            cp = <optimized out>
    #5  0xb6d1b5fb in _int_free (av=0xb3400010, p=<optimized out>, have_lock=0) at malloc.c:3996
            size = 32968
            fb = <optimized out>
            nextchunk = 0xb340b298
            nextsize = <optimized out>
            nextinuse = <optimized out>
            prevsize = <optimized out>
            bck = <optimized out>
            fwd = <optimized out>
            errstr = 0x0
            locked = 1
            __func__ = "_int_free"
    #6  0xb707f476 in QArrayData::deallocate(QArrayData*, unsigned int, unsigned int) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #7  0xb7084b89 in QByteArray::clear() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #8  0xb764590a in QAbstractSocket::disconnectFromHost() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Network.so.5
    No symbol table info available.
    #9  0x0808f0b4 in MonitorHandler::readyRead (this=0x826a010) at ../nntpProxyQT/monitorhandler.cpp:69
            line = {static MaxSize = 1073741808, d = 0xb340f318}
            str = {static null = {<No data fields>}, d = 0xb3403190}
            __PRETTY_FUNCTION__ = "void MonitorHandler::readyRead()"
    #10 0x0808f802 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (MonitorHandler::*)()>::call(void (MonitorHandler::*)(), MonitorHandler*, void**) (f=(void (MonitorHandler::*)(MonitorHandler * const)) 0x808efa4 <MonitorHandler::readyRead()>, o=0x826a010, arg=0xb3df1f1c) at /opt/Qt5.5.1/5.5/gcc/include/QtCore/qobjectdefs_impl.h:501
    No locals.
    #11 0x0808f7b3 in QtPrivate::FunctionPointer<void (MonitorHandler::*)()>::call<QtPrivate::List<>, void>(void (MonitorHandler::*)(), MonitorHandler*, void**) (f=(void (MonitorHandler::*)(MonitorHandler * const)) 0x808efa4 <MonitorHandler::readyRead()>, o=0x826a010, arg=0xb3df1f1c) at /opt/Qt5.5.1/5.5/gcc/include/QtCore/qobjectdefs_impl.h:520
    No locals.
    #12 0x0808f74a in QtPrivate::QSlotObject<void (MonitorHandler::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (which=1, this_=0xb3403028, r=0x826a010, a=0xb3df1f1c, ret=0x0) at /opt/Qt5.5.1/5.5/gcc/include/QtCore/qobject_impl.h:143
    No locals.
    #13 0xb7290598 in QMetaObject::activate(QObject*, int, int, void**) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #14 0xb729112d in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #15 0xb730f0e2 in QIODevice::readyRead() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #16 0xb7646030 in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Network.so.5
    No symbol table info available.
    #17 0xb763965a in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Network.so.5
    No symbol table info available.
    #18 0xb7653c1f in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Network.so.5
    No symbol table info available.
    #19 0xb72615fc in QCoreApplicationPrivate::notify_helper(QObject*, QEvent*) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #20 0xb7261760 in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #21 0xb72b9425 in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #22 0xb4f68da4 in g_main_context_dispatch () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #23 0xb4f690c9 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #24 0xb4f69196 in g_main_context_iteration () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #25 0xb72b8dbc in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #26 0xb725ed13 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #27 0xb725f18a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #28 0xb7078c85 in QThread::exec() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #29 0xb7078d58 in QThread::run() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #30 0xb707df60 in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #31 0xb6faeefb in start_thread (arg=0xb3df2b40) at pthread_create.c:309
            __res = <optimized out>
            pd = 0xb3df2b40
            now = <optimized out>
            unwind_buf = {cancel_jmp_buf = {{jmp_buf = {-1224994816, -1277220032, 4001536, -1277221848, 412061843, 1393877145}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
            not_first_call = <optimized out>
            pagesize_m1 = <optimized out>
            sp = <optimized out>
            freesize = <optimized out>
            __PRETTY_FUNCTION__ = "start_thread"
    #32 0xb6d9162e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:129
    No locals.
    
    Thread 3 (Thread 0xb4708b40 (LWP 5063)):
    #0  0xb7719d40 in __kernel_vsyscall ()
    No symbol table info available.
    #1  0xb6fb3015 in pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/pthread_cond_timedwait.S:245
    No locals.
    #2  0xb707eebd in QWaitCondition::wait(QMutex*, unsigned long) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #3  0xb707af1a in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #4  0xb707df60 in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #5  0xb6faeefb in start_thread (arg=0xb4708b40) at pthread_create.c:309
            __res = <optimized out>
            pd = 0xb4708b40
            now = <optimized out>
            unwind_buf = {cancel_jmp_buf = {{jmp_buf = {-1224994816, -1267692736, 4001536, -1267694552, 1204785308, 1393877145}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
            not_first_call = <optimized out>
            pagesize_m1 = <optimized out>
            sp = <optimized out>
            freesize = <optimized out>
            __PRETTY_FUNCTION__ = "start_thread"
    #6  0xb6d9162e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:129
    No locals.
    
    Thread 1 (Thread 0xb4eae700 (LWP 5054)):
    #0  0xb7719d40 in __kernel_vsyscall ()
    No symbol table info available.
    #1  0xb6d86deb in poll () at ../sysdeps/unix/syscall-template.S:81
    No locals.
    #2  0xb4f780b0 in g_poll () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #3  0xb4f69054 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #4  0xb4f69196 in g_main_context_iteration () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #5  0xb72b8dbc in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #6  0xb725ed13 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #7  0xb725f18a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #8  0xb726728a in QCoreApplication::exec() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #9  0x0804e12d in main (argc=1, argv=0xbf944b44) at ../nntpProxyQT/main.cpp:45
            app = <incomplete type>
            theProxy = 0x82310e8
            configFile = 0x0
    
    

    Now it's seems to be around the disconnectFromHost call...
    I find really weird that if I don't use the QString for the logging I don't get the crash...



  • I changed my code to be like this:

    void MonitorHandler::readyRead(){
        if(iSocket->canReadLine()){
            QString line(iSocket->readLine());
    
            if (line.startsWith(sCmds.QUIT, Qt::CaseInsensitive)
                    || line.startsWith(sCmds.EXIT, Qt::CaseInsensitive)){
                iSocket->disconnectFromHost();
            } else {
                write("plop\n");
            }
        }
    }
    

    and I'm getting a crash on the disconnectFromHost.

    
    Thread 4 (Thread 0xb3dffb40 (LWP 5922)):
    #0  0xb775fd40 in __kernel_vsyscall ()
    No symbol table info available.
    #1  0xb6d1c307 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
            resultvar = <optimized out>
            resultvar = <optimized out>
            pid = -1226227712
            selftid = 5922
    #2  0xb6d1d9c3 in __GI_abort () at abort.c:89
            save_stage = 2
            act = {__sigaction_handler = {sa_handler = 0xb72adce6 <QEvent::~QEvent()+6>, sa_sigaction = 0xb72adce6 <QEvent::~QEvent()+6>}, sa_mask = {__val = {3075987008, 3070124032, 3007327008, 3069464150, 3007315984, 3069464232, 3007361808, 3073039718, 1, 3075987008, 3007327328, 3007327328, 3076002160, 3072111140, 3007327328, 1, 3076561369, 3070124032, 3007327328, 3007327328, 3076002160, 3069464168, 0, 3007327328, 3076002160, 3077108951, 3077108903, 3069464150, 3077944004, 0, 3, 4096}}, sa_flags = -1227018408, sa_restorer = 0x1000}
            sigs = {__val = {32, 0 <repeats 31 times>}}
    #3  0xb6d5a6f8 in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0xb6e5065c "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
            ap = <optimized out>
            fd = 10
            on_2 = <optimized out>
            list = <optimized out>
            nlist = <optimized out>
            cp = <optimized out>
            written = <optimized out>
    #4  0xb6d6076a in malloc_printerr (action=<optimized out>, str=0xb6e4c138 "corrupted double-linked list", ptr=0xb3403188) at malloc.c:4996
            buf = "b3403188"
            cp = <optimized out>
    #5  0xb6d61793 in _int_free (av=0xb3400010, p=<optimized out>, have_lock=0) at malloc.c:3987
            size = 33040
            fb = <optimized out>
            nextchunk = 0xb340b298
            nextsize = <optimized out>
            nextinuse = <optimized out>
            prevsize = <optimized out>
            bck = <optimized out>
            fwd = <optimized out>
            errstr = 0x0
            locked = 1
            __func__ = "_int_free"
    #6  0xb70c5476 in QArrayData::deallocate(QArrayData*, unsigned int, unsigned int) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #7  0xb70cab89 in QByteArray::clear() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #8  0xb768b90a in QAbstractSocket::disconnectFromHost() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Network.so.5
    No symbol table info available.
    #9  0x0808f00d in MonitorHandler::readyRead (this=0x982ece0) at ../nntpProxyQT/monitorhandler.cpp:71
            line = {static null = {<No data fields>}, d = 0xb3402998}
    #10 0x0808f906 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (MonitorHandler::*)()>::call(void (MonitorHandler::*)(), MonitorHandler*, void**) (f=(void (MonitorHandler::*)(MonitorHandler * const)) 0x808ef3a <MonitorHandler::readyRead()>, o=0x982ece0, arg=0xb3dfef1c) at /opt/Qt5.5.1/5.5/gcc/include/QtCore/qobjectdefs_impl.h:501
    No locals.
    #11 0x0808f8b7 in QtPrivate::FunctionPointer<void (MonitorHandler::*)()>::call<QtPrivate::List<>, void>(void (MonitorHandler::*)(), MonitorHandler*, void**) (f=(void (MonitorHandler::*)(MonitorHandler * const)) 0x808ef3a <MonitorHandler::readyRead()>, o=0x982ece0, arg=0xb3dfef1c) at /opt/Qt5.5.1/5.5/gcc/include/QtCore/qobjectdefs_impl.h:520
    No locals.
    #12 0x0808f84e in QtPrivate::QSlotObject<void (MonitorHandler::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (which=1, this_=0xb3403028, r=0x982ece0, a=0xb3dfef1c, ret=0x0) at /opt/Qt5.5.1/5.5/gcc/include/QtCore/qobject_impl.h:143
    No locals.
    #13 0xb72d6598 in QMetaObject::activate(QObject*, int, int, void**) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #14 0xb72d712d in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #15 0xb73550e2 in QIODevice::readyRead() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #16 0xb768c030 in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Network.so.5
    No symbol table info available.
    #17 0xb767f65a in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Network.so.5
    No symbol table info available.
    #18 0xb7699c1f in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Network.so.5
    No symbol table info available.
    #19 0xb72a75fc in QCoreApplicationPrivate::notify_helper(QObject*, QEvent*) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #20 0xb72a7760 in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #21 0xb72ff425 in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #22 0xb4faeda4 in g_main_context_dispatch () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #23 0xb4faf0c9 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #24 0xb4faf196 in g_main_context_iteration () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #25 0xb72fedbc in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #26 0xb72a4d13 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #27 0xb72a518a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #28 0xb70bec85 in QThread::exec() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #29 0xb70bed58 in QThread::run() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #30 0xb70c3f60 in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #31 0xb6ff4efb in start_thread (arg=0xb3dffb40) at pthread_create.c:309
            __res = <optimized out>
            pd = 0xb3dffb40
            now = <optimized out>
            unwind_buf = {cancel_jmp_buf = {{jmp_buf = {-1224708096, -1277166784, 4001536, -1277168600, 570784379, 1669204593}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
            not_first_call = <optimized out>
            pagesize_m1 = <optimized out>
            sp = <optimized out>
            freesize = <optimized out>
            __PRETTY_FUNCTION__ = "start_thread"
    #32 0xb6dd762e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:129
    No locals.
    
    Thread 3 (Thread 0xb474eb40 (LWP 5921)):
    #0  0xb775fd40 in __kernel_vsyscall ()
    No symbol table info available.
    #1  0xb6ff9015 in pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/pthread_cond_timedwait.S:245
    No locals.
    #2  0xb70c4ebd in QWaitCondition::wait(QMutex*, unsigned long) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #3  0xb70c0f1a in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #4  0xb70c3f60 in ?? () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #5  0xb6ff4efb in start_thread (arg=0xb474eb40) at pthread_create.c:309
            __res = <optimized out>
            pd = 0xb474eb40
            now = <optimized out>
            unwind_buf = {cancel_jmp_buf = {{jmp_buf = {-1224708096, -1267406016, 4001536, -1267407832, 1948613236, 1669204593}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
            not_first_call = <optimized out>
            pagesize_m1 = <optimized out>
            sp = <optimized out>
            freesize = <optimized out>
            __PRETTY_FUNCTION__ = "start_thread"
    #6  0xb6dd762e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:129
    No locals.
    
    Thread 1 (Thread 0xb4ef4700 (LWP 5912)):
    #0  0xb775fd40 in __kernel_vsyscall ()
    No symbol table info available.
    #1  0xb6dccdeb in poll () at ../sysdeps/unix/syscall-template.S:81
    No locals.
    #2  0xb4fbe0b0 in g_poll () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #3  0xb4faf054 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #4  0xb4faf196 in g_main_context_iteration () from /lib/i386-linux-gnu/libglib-2.0.so.0
    No symbol table info available.
    #5  0xb72fedbc in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #6  0xb72a4d13 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #7  0xb72a518a in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #8  0xb72ad28a in QCoreApplication::exec() () from /opt/Qt5.5.1/5.5/gcc/lib/libQt5Core.so.5
    No symbol table info available.
    #9  0x0804e08d in main (argc=1, argv=0xbfeb3b24) at ../nntpProxyQT/main.cpp:45
            app = <incomplete type>
            theProxy = 0x97cb0e8
            configFile = 0x0
    
    


  • It seems that when I disconnect the socket, I go straight to my disconnection handler where I delete the socket.
    At this point when it tries to come back to readyRead, it is crashing on the destruction of the QString built on the QByteArray maybe coming from the buffer of the socket that has been freed?

    I don't have the issue if I'm putting the string in the heap:

    void MonitorHandler::readyRead(){
        if(iSocket->canReadLine()){
            QString *line = new QString(iSocket->readLine());
    
    #ifdef LOG_MONITOR_DATA
            QString str("Data In: ");
            str += *line;
            qDebug() << str;
    //        _log(str);
    #endif
    
            if (line->startsWith(sCmds.QUIT, Qt::CaseInsensitive)
                    || line->startsWith(sCmds.EXIT, Qt::CaseInsensitive)){
                delete line;
                line = Q_NULLPTR;
                iSocket->disconnectFromHost();
            } else {
    
                write("plop\n");
            }
            delete line;
        }
        qDebug() << "readyRead <<<";
    }
    

    But I don't find this really elegant...
    Any suggestion on how I could this in a better way?

    My Server only accepts one connection at a time, rejects new ones when it is busy. When the client exit, I would like to delete the iSocket and set it to NULL as it is the way I know if the server is busy or not.


  • Qt Champions 2016

    You could make this connection
    connect(iSocket, &QTcpSocket::disconnected, this, &MonitorHandler::disconnected);
    to be queued. Or instead of deleting your socket with delete you could use QObject::deleteLater().

    Kind regards.



  • Thanks, I thought I tried and it didn't work but probably I queued the wrong connection.
    I'll take this option to queue the disconnect call of the socket. I'll keep the delete of the socket as I want to make sure the pointer is then set to NULL.


  • Qt Champions 2016

    @mbruel
    If you want to be notified of the socket deletion and still wish to use deleteLater you could hold the pointer not as QTcpSocket *, but as a QPointer<QTcpSocket> instead. In that case when the socket is deleted by Qt (through processing of the events) the QPointer instance will be set to point to NULL automatically.

    Kind regards.



  • @kshegunov
    I'm trying QPointers and I'm having a compilation issue with the one of my QTextStream. I don't understand what is the problem.
    Here is what I did:

    definition:
        QPointer<QTcpSocket>   iSocket;
        QPointer<QTextStream>  iStream;
    
    void MonitorServer::newConnection(){
        QTcpSocket *sock = iServer->nextPendingConnection();
        if (iSocket.isNull()){
            _log("Ignore Connection: Monitor Server has already a local connection...");
            sock->write("Already a connection in use...\n");
            sock->flush();
            delete sock;
        } else {
            iSocket = sock;
            iStream = new QTextStream(sock);
    
            connect(this, &MonitorServer::destroyMonitorConnection, iSocket.data(), &QObject::deleteLater);
            connect(this, &MonitorServer::destroyMonitorConnection, iStream.data(), &QObject::deleteLater);
    
    }
    

    I'm getting this issue:

    monitorserver.cpp:62: error: no matching function for call to 'MonitorServer::connect(MonitorServer*, void (MonitorServer::*)(), QTextStream*, void (QObject::*)())'
             connect(this, &MonitorServer::destroyMonitorConnection, iStream.data(), &QObject::deleteLater);
                                                                                                          ^
    

    It must be silly but I don't see why I'm getting this issue with the QTextStream and not with the QTcpSocket...

    PS: Here is my code now for the deletion:

    void MonitorServer::disconnected(){
        _log("disconnected...");
        emit destroyMonitorConnection();
    }
    

  • Qt Champions 2016

    Hello,

    It must be silly but I don't see why I'm getting this issue with the QTextStream and not with the QTcpSocket...

    You're getting an error simply because QTextStream is not a QObject subclass, so it doesn't have signals, nor slots and you can't use it with QPointer. QPointer is specifically tailored to be used with QObject pointers, and not with any class. If you wish you could use QScopedPointer for the text stream or just create an instance on the stack when you're reading the socket (which would be my preference). For example:

    void MonitorHandler::readyRead()
    {
        // ... Some code
        QTextStream inputStream(iSocket);
        // ... Read from the stream while there's data pending:
        while (!inputStream.atEnd())  {
            QString line = inputStream.readLine();
            // ... Do something with line you've read
        }
    }
    

    Kind regards.



  • @kshegunov
    ok I see, I thought all QT objects where inherited from QObject which in fact doesn't make sense as we can only inherit once from QObject...
    For the QTextStream, using a local object on the stack means it will be initialised every time the socket receive information... I find it a not efficient so I'll keep a normal pointer.
    Thanks for all your advices.
    I start to really love QT :)


  • Qt Champions 2016

    @mbruel said:

    as we can only inherit once from QObject...

    This is news to me, how come you can only inherit once? You can subclass QObject as many times as you wish.

    For the QTextStream, using a local object on the stack means it will be initialised every time the socket receive information... I find it a not efficient so I'll keep a normal pointer.

    This point is moot in your case. If you've profiled your code and indeed you're certain that creating a QTextStream on each read is in fact a bottleneck, then and only then you can think about optimization. If you don't wish to create the object everytime just put it globally in your class and on each connect set the QIODevice for the text stream. What's the point in creating the object in the heap really? You gain nothing but an obligation to clean the memory up at some point. Instead you could put a simple QTextStream stream; declaration in your class and call stream.setDevice(socket) when your socket is initialized, like this:

    class MonitorServer : public QObject
    {
        // ... Put your code 
    private:
        QTextStream stream;
    };
    
    void MonitorServer::newConnection()
    {
        QTcpSocket * sock = iServer->nextPendingConnection();
        if (!sock)  {  // No pending connection (handle error accordingly)
        }
    
        // Ready to accept the connection ... set the stream's IO device
        stream.setDevice(sock);
    }
    
    void MonitorHandler::readyRead()
    {
        // ... Read ... read ... read
        if (line->startsWith(sCmds.QUIT, Qt::CaseInsensitive) || line->startsWith(sCmds.EXIT, Qt::CaseInsensitive))  {
            stream.setDevice(NULL);    //< This will flush the buffer to the device if any data is pending
            iSocket->disconnectFromHost();
        }
        // ... More code
    }
    

    The same goes for the QStrings you're using. QString is implicitly shared so instead of making your code more optimized by creating the QString in the heap, you're gaining absolutely nothing, only potential memory leaks!



  • @kshegunov said:

    You can subclass QObject as many times as you wish.

    Well that was my impression. For what I remember when I started my project I couldn't inherit from both QTcpSocket and QThread... I don't remember the reason, I thought it had to do with the fact I was inheriting twice from QObject... Maybe it was not that...

    @kshegunov said:

    What's the point in creating the object in the heap really? You gain nothing but an obligation to clean the memory up at some point. Instead you could put a simple QTextStream stream; declaration in your class and call stream.setDevice(socket) when your socket is initialized, like this:

    Well that was my first intention but I looked at the doc of setDevice which states that when the QTextStream is reassigned there is a flush on the old device. I guess there is a test to check if the device exists and is opened but I was lazy to check so I went for a new one in the heap for each connection as the old socket would have been destroyed.
    Now that my project is nearly finished and quite tested, I may go back to this as indeed it is more clean.

    @kshegunov said:

    so instead of making your code more optimized by creating the QString in the heap, you're gaining absolutely nothing, only potential memory leaks!

    I'm not using any QString on the heap.... The example I've put in my 3rd of 4th was just to attempts to identify the cause of the crash when my socket was closing... It was just some debug tests. By using your solution to queue the disconnect call, I went back to a normal local string on the stack.

    I'll have a read of your links.
    Cheers


  • Qt Champions 2016

    @mbruel
    Hello,

    Well that was my impression. For what I remember when I started my project I couldn't inherit from both QTcpSocket and QThread... I don't remember the reason, I thought it had to do with the fact I was inheriting twice from QObject... Maybe it was not that...

    I guess there was a bit of misunderstanding here. I meant that you can construct a hierarchy based on QObject without any restriction on the depth. You were talking of multiple inheritance. With multiple inheritance you should not extend two classes that are from the same hierarchy (with some very fine exceptions to that rule) and if in the end you do that should be a virtual inheritance like this:

    class BadClass : public virtual BaseClass1, public virtual BaseClass2  {};
    

    In any case you shouldn't be subclassing QThread not to mention both QThread and QTcpSocket. Your new class is not a thread and a socket at the same time, is it?

    I'm not using any QString on the heap.... The example I've put in my 3rd of 4th was just to attempts to identify the cause of the crash when my socket was closing... It was just some debug tests.

    Okay, in that case you can disregard the comment. Still, in my opinion, one should be striving to use as little heap allocations as possible. In the end each QObject is dragging a private object that is allocated in the heap, and each implicitly shared class is doing the same but with a shared data object. So if you have a class that inherits from QObject there is nothing wrong in declaring your variables directly, instead of creating them in the heap and using the returned pointers.

    Kind regards.



  • @kshegunov

    In any case you shouldn't be subclassing QThread not to mention both QThread and QTcpSocket. Your new class is not a thread and a socket at the same time, is it?

    Well it was before knowing how QThread works, I thought the whole object, including its slots would be in the thread. That's why I wanted to have my Connection class to be a threaded socket. After a bit of reading I realised it doesn't work like this but that we should moveToThread instead.

    @kshegunov

    So if you have a class that inherits from QObject there is nothing wrong in declaring your variables directly, instead of creating them in the heap and using the returned pointers.

    Yeah that's true. But pointers are still needed when you want to extend the scope of the objects and share them between different objects or also just have an handle independently of the instance (QTcpSocket handle pointing on a QTcpSocket or a QSslSocket)

    I've just read your link about Implicit sharing, that's interesting to know. There are not so many classes but yeah QByteArray and QString are quite common. I suppose my crash was due to this sharing even between a QString built on a implicit shared QByteArray. I would have expect thus that there would be a copy done at detach time when the source QByteArray is destroyed but still have a local QString using the data...


  • Qt Champions 2016

    @mbruel

    Yeah that's true. But pointers are still needed when you want to extend the scope of the objects and share them between different objects or also just have an handle independently of the instance (QTcpSocket handle pointing on a QTcpSocket or a QSslSocket)

    I don't argue that. But in your case the QTextStream is locally used, so to allocate in the heap is not as beneficial. In any case this is mostly depending on your preference (i.e. moc generates everything in the heap), I was just giving my opinion.

    There are not so many classes but yeah QByteArray and QString are quite common.

    In fact many classes in Qt are implicitly shared, including all the container (QList, QVector and the like) the images/pixmaps (QImage, QPixmap), strings and byte arrays, if memory serves me QVariant and more.

    I suppose my crash was due to this sharing even between a QString built on a implicit shared QByteArray.

    I doubt it. Probably your stack got corrupted and that's why you got the crash. Implicitly shared classes (as to my knowledge) are detaching-thread-safe - meaning that the data copying (which is occurring internally in the background) is thread safe.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.