[SOLVED] QSerialPort and Invalid address specified to RtlFreeHeap



  • I have encountered a problem which is connected with QSerialPort. I am receiving a message from debugger as follows:
    Invalid address specified to RtlFreeHeap
    Inside function call list window I was able to identify it as a problem with QSerialPort. Furthermore, I have narrowed the problem to the read() method from QSerialPort class. Is there something that can be done about it?



  • Please give simple example project that reproduce a problem. Also, what version of QtSerialPort do you use?



  • It is hard to give a simple example because the problem I am encountering is a part of a bigger project. However, I will create a test project and check if the same problem occurs there.
    I'm using QSerialPort which comes with Qt 5.3.1.



  • Unfortunately for me I can not reproduce this error with simple example. This does not occur with just reading the data from QSerialPort.
    I think that it can be something connected to threads and simultaneous access to the memory. However, I have also excluded that because I have a wrapper class for QSerialPort and mutex which guards the access to the device. So, I think this is not the case.



  • It means that most likely your problem in the your application with lot of threads and mutexes. I at all don't understand, why you to use threads (with mutexes). For me it is strange approach...



  • I am using threads and mutexes because I share memory between them.
    Yes, it may seem that the problem is with all the threads. However, using QSerialPort wasn't my first shoot. Before that I have written a library which works both for Windows and Linux system. It was fine until I decided to abandon this because I wanted to focus on the application development not on the interfaces. Also I have tested serial port support from ASIO boost. It was very good solution and it worked. Once again I also decided to abandon this because of long time which is required for compilation, and as far as I know it doesn't have forward declarations to speed up the process.
    As you can see this is not the problem with multiple threads and mutexes. It has something to do with the QSerialPort.
    Furthermore, Invalid address specified to RtlFreeHeap isn't the only problem I have got with QSerialPort. In early Qt 5 versions when it had support for this class almost out of the box it had some problems with QStreams. Now, it has problems with memory deallocation (in debug mode) and with QList (element out of the reach in release mode).
    Are there any other good alternatives which have multi platform support and are relatively light?



  • [quote]
    Furthermore, Invalid address specified to RtlFreeHeap isn’t the only problem I have got with QSerialPort. In early Qt 5 versions when it had support for this class almost out of the box it had some problems with QStreams.
    [/quote]

    These are all unfounded statements which have no value. And it isn't important that you there wrote your wrappers at yourselves earlier.

    You at all didn't provide any code. Therefore, most likely a problem in your code.

    [quote]
    Are there any other good alternatives which have multi platform support and are relatively light?
    [/quote]

    Use boost::asio or your custom wrapper, what problem?



  • This is exactly why I have written what I had used before. Therefore, I'm pretty convenient that the error isn't because of my code. Also I've given a reason why I don't use other solutions any more.

    Here is the function trace when I get the message with error:
    0 ntdll!RtlpNtSetValueKey C:\Windows\SYSTEM32\ntdll.dll 0x770713f7
    1 ntdll!RtlpNtSetValueKey C:\Windows\SYSTEM32\ntdll.dll 0x77070311
    2 ntdll!LdrSetAppCompatDllRedirectionCallback C:\Windows\SYSTEM32\ntdll.dll 0x77024e37
    3 ?? 0x1662d998
    4 ntdll!RtlFreeHeap C:\Windows\SYSTEM32\ntdll.dll 0x76fcfac9
    5 msvcrt!free C:\Windows\SysWOW64\msvcrt.dll 0x767b9a15
    6 ?? 0x141d0000
    7 QArrayData::deallocate 130 0x6b799e14
    8 QTypedArrayData<char>::deallocate 234 0x6b9cb89d
    9 QByteArray::resize 1448 0x6b79bc2b
    10 QRingBuffer::append 383 0x6458963e
    11 QSerialPortPrivate::_q_completeAsyncRead 608 0x645855af
    12 QSerialPort::qt_static_metacall 348 0x64582d8e
    13 QMetaObject::activate 3680 0x6b954ee9
    14 QMetaObject::activate 3546 0x6b95484e
    15 QWinEventNotifier::activated 134 0x6b9ad11d
    16 QWinEventNotifier::event 241 0x6b976955
    17 QApplicationPrivate::notify_helper 3522 0x8c1e09f
    18 QApplication::notify 2975 0x8c1bb51
    19 QCoreApplication::notifyInternal 935 0x6b929dde
    20 QCoreApplication::sendEvent 237 0x6b9cf187
    21 QEventDispatcherWin32Private::activateEventNotifier 335 0x6b978188
    22 QEventDispatcherWin32::processEvents 759 0x6b979887
    23 QWindowsGuiEventDispatcher::processEvents 80 0x6285cdc0
    24 QEventLoop::processEvents 136 0x6b927e84
    25 QEventLoop::exec 212 0x6b92811f
    26 QCoreApplication::exec 1188 0x6b92a42d
    27 QGuiApplication::exec 1450 0xb062e2
    28 QApplication::exec 2767 0x8c1b495
    29 qMain main.cpp 10 0x401653
    30 WinMain@16 131 0x408a7d
    31 main 0x41cccd

    If you could please look at entry 8 to 12 you will see that something is going on with QSerialPort. I get this message randomly but mos often at the very beginning of the transmission.



  • It doesn't speak about anything that problem is in QtSerialPort. Once again I will repeat: most likely you do something wrong (I am sure). But without a source code I can help nothing.

    UPD: The most important mistake - the QtSerialPort can't use from different threads (even if to use mutexes, etc.). Because internally the QtSerialPort works not as you think.



  • How it doesn't say nothing about QSerialPort? There are:
    11 QSerialPortPrivate::_q_completeAsyncRead 608 0×645855af
    12 QSerialPort::qt_static_metacall 348 0×64582d8e
    which indicates that it operates on the memory and then the crash occurs.

    When I've used for example boost for reading from serial port nothing like that happened.

    Update:
    Here is the source code responsible for reading data from QSerialPort:

    @
    int ComPort::read( char * Buffer, int Count)
    {
    int i;

    mutex.lock();
    
    if( !_Port.isOpen())
    {
      mutex.unlock();
      return -2;
    }
    
    int available_bytes;
    
    available_bytes = _Port.bytesAvailable();
    
    if( Count <= available_bytes)
      available_bytes = Count;
    
    qDebug() << "<- in";
    i = _Port.read( Buffer, available_bytes);
    qDebug() << "-> out";
    
    mutex.unlock();
    
    return i;
    

    }
    @

    During debugging I can only get "<- in" string but no "-> out".

    Update:
    So, is there a workaround to do this? I mean using QSerialPort from another thread.



  • bq. Here is the source code responsible for reading data from QSerialPort:

    This is wrong. Because port.read() reads data from the internal buffer of class (QRingBuffer). Thus, this internal buffer isn't protected on write to it. This writing to the read buffer (buffer.append()) is carried out inside of the class when RX_EVENT triggered. So, it lead to data corruption in your case.

    So, you all do wrong..

    bq. So, is there a workaround to do this? I mean using QSerialPort from another thread.

    You should move whole QtSerialPort instance to another thread (i.e. access to the all serial port's methods has to be provided always from one thread). And then use signals/slots for data transferring. In this case the mutexes do not need at all.



  • I did what you suggested with several variations.
    Like before I have wrapper class for QSerialPort:

    @ ComPort::ComPort(QObject *parent) :
    _BytesWaiting(0),
    _BaudRate( QSerialPort::Baud115200),
    _Parity( QSerialPort::NoParity),
    _StopBits( QSerialPort::OneStop),
    _FlowControl( QSerialPort::NoFlowControl),
    _DataBits( QSerialPort::Data8),
    QObject(parent),
    Stream(Buffer)
    {
    ThreadCom = new QThread;
    _Port = new QSerialPort();

    connect(_Port, SIGNAL(readyRead()), this, SLOT(handleReadyRead()));
    
    _Port->moveToThread( ThreadCom);
    ThreadCom->start();
    

    }@

    Also in the GUI I have:

    @ ThreadForCom = new QThread;
    SerialPort = new ComPort::ComPort();
    SerialPort->moveToThread(ThreadForCom);

    ThreadForCom->start();@

    However, this doesn't work. I don't get any data. But when in my wrapper class I let go of QThread:

    @ ComPort::ComPort(QObject *parent) :
    _BytesWaiting(0),
    _BaudRate( QSerialPort::Baud115200),
    _Parity( QSerialPort::NoParity),
    _StopBits( QSerialPort::OneStop),
    _FlowControl( QSerialPort::NoFlowControl),
    _DataBits( QSerialPort::Data8),
    QObject(parent),
    Stream(Buffer)
    {
    _Port = new QSerialPort();

    connect(_Port, SIGNAL(readyRead()), this, SLOT(handleReadyRead()));
    

    }@

    It works but not completely. It seams that I'm loosing data and also the messages which I get are corrupted.

    Edit:
    Here is how I handle the oncoming data:
    @ void ComPort::handleReadyRead(void)
    {
    mutex.lock();
    Buffer.append(_Port->readAll());
    mutex.unlock();
    }@

    Here is reading procedure:
    @int ComPort::read( char * Buffer, int Count)
    {
    mutex.lock();

    if( !_Port->isOpen())
    {
      mutex.unlock();
      return -2;
    }
    
    int available_bytes;
    
    available_bytes = this->Buffer.count();
    
    if( Count <= available_bytes)
      available_bytes = Count;
    
    memcpy( Buffer, this->Buffer.data(), available_bytes);
    this->Buffer.remove(0, available_bytes);
    
    mutex.unlock();
    
    return available_bytes;
    

    }@



  • @
    class Worker : public QSerialPort
    {
    public:
    Worker(QObject *parent = 0)
    : QSerialPort(parent)
    {

        open(...);
        setBaudRate(...);
        ...
        setParity(...);
    
        conenct(this, SIGNAL(readyRead()), this, SLOT(handleReadyRead()));
    }
    

    signals:
    void dataReceived(constQByteArray &data);

    private slots:
    void handleReadyRead()
    {
    const QByteArray data = readAll();
    emit dataReceived(data);
    }
    }

    ...
    worker = new Worker();
    thread = new QThread();
    worker->moveToThread(thread);
    thread->start();
    ...
    @



  • I did apply your suggestions. Now, I don't have a single mutex in my application. After some changes everything is working in signal/slot spirit. However, it seems like data are being lost, actually like lots of it is corrupted. This also happened before the change. What can be responsible for this?



  • bq. However, it seems like data are being lost, actually like lots of it is corrupted.

    It can't be in principle (impossible).

    bq. What can be responsible for this?

    Try to check for correct configuration of your serialport.



  • Problem was solved. Now everything works just fine.
    The reason for the message being corrupted was the way of handling the data. It required me to remove the data from temporary buffer. Unless the algorithm would look for start sequence inside the data which has been already processed.

    To sum up the main problem of the Invalid address specified to RtlFreeHeap. QSerialPort can't be used between threads even the memory is protected by mutexes.


Log in to reply
 

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