【发布时间】:2015-10-21 19:01:35
【问题描述】:
我正在使用 QSerialPort 与硬件设备通信。新数据不会发出“readyRead”信号,所以我决定使用 QThread 编写一个读取线程。
这是代码:
void ReadThread::run()
{
while(true){
readData();
if (buffer.size() > 0) parseData();
}
}
和
void ReadThread::readData()
{
buffer.append(device->readAll();
}
缓冲区是一个私有 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()”,就不会再出现崩溃(当然也就无法解析数据了)。
有人知道这可能是什么吗?
【问题讨论】:
-
新数据不会发出“readyRead”-信号 - 我认为你应该先研究一下。 QSerialport 是从 QIODevice 派生的,所以当数据可用时它当然应该发出 readyRead。
-
我猜想你正在某个地方写内存超出分配块的范围,但不在你提供的代码中。您是否尝试过任何其他工具,例如 valgrind 或电动围栏?
-
@TheDarkKnight 是的,我当然会看看这个。
-
@DarkFalcon 我没有通过 QSerialPort 写入设备。实际上,我只需要 QSerialPort 的“readAll”功能。使用 valdrind(通过 QtCreator)运行程序有一个有趣的效果,即程序不会崩溃(运行时间超过 24 小时)。
-
@boltzmann138:如果它在 valgrind 下成功运行,那么这听起来像是一个竞态条件。在 valgrind 下运行的一个副作用是所有线程都被调度在一个虚拟 CPU 上,这意味着与真正的 CPU 不同,在任何给定时间只能执行一个线程。 Valentin Heinitz 可能走在正确的轨道上。
标签: c++ qt segmentation-fault