c++ - 如果在 while 循环中调用,QSerialPort::readAll() 会导致 SIGSEGV/SIGABRT

标签 c++ qt segmentation-fault

我正在使用 QSerialPort 与硬件设备通信。新数据不会发出“readyRead”信号,所以我决定使用 QThread 编写一个读取线程。

这是代码:

void ReadThread::run()
{
    while(true){
        readData();
        if (buffer.size() > 0) parseData();
    }
}

void ReadThread::readData()
{
    buffer.append(device->readAll();
}

缓冲区是私有(private) QByteArray,设备是指向 QSerialPort 的指针。 ParseData 将解析数据并发出一些信号。剩余 parseData 时清除缓冲区。

这是有效的,但是在一段时间后(有时是 10 秒,有时是 1 小时)程序因 SIGSEGV 崩溃并出现以下跟踪:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff3498700 (LWP 24870)]
malloc_consolidate (av=av@entry=0x7fffec000020) at malloc.c:4151
(gdb) bt
#0  malloc_consolidate (av=av@entry=0x7fffec000020) at malloc.c:4151
#1  0x00007ffff62c2ee8 in _int_malloc (av=av@entry=0x7fffec000020, bytes=bytes@entry=32769) at malloc.c:3423
#2  0x00007ffff62c4661 in _int_realloc (av=av@entry=0x7fffec000020, oldp=oldp@entry=0x7fffec0013b0, oldsize=oldsize@entry=64, nb=nb@entry=32784) at malloc.c:4286
#3  0x00007ffff62c57b9 in __GI___libc_realloc (oldmem=0x7fffec0013c0, bytes=32768) at malloc.c:3029
#4  0x00007ffff70d1cdd in QByteArray::reallocData(unsigned int, QFlags<QArrayData::AllocationOption>) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#5  0x00007ffff70d1f07 in QByteArray::resize(int) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#6  0x00007ffff799f9fc in free (bytes=<optimized out>, this=0x609458)
    at ../../include/QtSerialPort/5.3.2/QtSerialPort/private/../../../../../src/serialport/qt4support/include/private/qringbuffer_p.h:140
#7  read (maxLength=<optimized out>, data=<optimized out>, this=0x609458)
    at ../../include/QtSerialPort/5.3.2/QtSerialPort/private/../../../../../src/serialport/qt4support/include/private/qringbuffer_p.h:326
#8  QSerialPort::readData (this=<optimized out>, data=<optimized out>, maxSize=<optimized out>) at qserialport.cpp:1341
#9  0x00007ffff722bdf0 in QIODevice::read(char*, long long) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#10 0x00007ffff722cbaf in QIODevice::readAll() () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#11 0x00007ffff7bd0741 in readThread::readData (this=0x6066c0) at ../reader.cpp:212
#12 0x00007ffff7bc80d0 in readThread::run (this=0x6066c0) at ../reader.cpp:16
#13 0x00007ffff70cdd2e in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#14 0x00007ffff6e1c0a4 in start_thread (arg=0x7ffff3498700) at pthread_create.c:309
#15 0x00007ffff632f04d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

我不确定如何正确重现该问题,因为它是随机出现的。如果我在我的 while 循环中注释掉“readData()”,则不会再出现崩溃(当然没有数据可以被解析)。

有人知道这是什么吗?

最佳答案

缓冲区是什么?难道,另一个线程正在从缓冲区中读取数据并随后将其清除?

尝试锁定它(以及线程之间共享的所有其他数据),例如带有互斥锁

QMutex mx; // could be also member of the ReadThread class

void ReadThread::readData()
{
    mx.lock();
    buffer.append(device->readAll();
    mx.unlock();
}

在从另一个线程读取和清除缓冲区的代码中做同样的事情(我没有做假设,这是 parseData())

另一种可能是,parseData() 调用一些在 GUI-Thread 中运行的代码。这在 Qt4 中不起作用,可能在 Qt5 中也不起作用

关于c++ - 如果在 while 循环中调用,QSerialPort::readAll() 会导致 SIGSEGV/SIGABRT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31723468/

相关文章:

PHPUnit 段错误 11

c++ - VS2010 中的链接器错误(解决方案和静态方法中有 2 个项目)

PHP preg_match_all 导致 Apache 段错误

c - 用C打开文件时出现段错误

c++ - Linux 进程可以拥有的最小进程 ID 是多少?

c++ - Qt永久删除文件

具有平台 API 的 C++ 全局热键

c++ - 实例的排序 vector

c++ - 使用标签调度时如何反转模板参数?

c++ - 使用 C++ 将一个 XML 文档转换为另一个