LINUX.ORG.RU

Падает консольное Qt-приложение, неясности с core-файлами

 , , ,


1

4

Приветствую! Столкнулся с периодическими вылетами проги, выполняющей прием данных с RS-232, их обработку, и выдачу пользовательских данных через RS-232 в два канала («передатчика»). Вылет может произойти и через 5 минут, и через пару часов.

Версия ОС:

Linux B7v5 3.2.0-27-generic #43astra9 SMP Fri Nov 2 01:34:28 MSK 2012 x86_64 GNU/Linux

Вкратце прога:

int main(int argc, char *argv[])
{
     QCoreApplication a(argc, argv);

    R913V Apd_r913v;

    //threads
    PRD Prd1(1,&Apd_r913v);
    PRD Prd2(2,&Apd_r913v);
    ReadFromRS232 ReadFromCom(&Apd_r913v);

    ReadFromCom.start();
    Prd1.start();
    Prd2.start();

    return a.exec();
}
class R913V : public QObject
{
   Q_OBJECT

public:
    R913V();
    ~R913V();

    ClientSocket *MS_WR_REG;     

    QMutex fkMutex, prdMutex, regMutex;
    QByteArray arrayBPU;

    qint16 out_COM_port(quint8*,qint32);
    void control_BPU(quint8);
    void write_BPU(bool);

signals:
    void toPRD1();
    void toPRD2();

};

class PRD : public QThread
{
    Q_OBJECT

public:
    PRD(quint8 channelNum,R913V *r913v);
    ~PRD();
    void run();


private:
    ServerSocket *MS_prd;
    ClientSocket *MS_ready_PRD;

    quint8 chanNum;
    R913V *r913v_apd;

    MesT_DRV  DRV;
    OUT_KDGR  OutKdgr;			

    MesT_OUT_KDGR  p_KDGR[8];
    T_Mess913v Message;
    OUT_KDGR  RegOutKdgr[8];
    int result;
    quint8 out_KDG[sizeof(MesT_OUT_KDGR)*8];
    T_OUT_KDGR_MESSAGE out_kdgr_message;

    QByteArray bytesForTrm;


    void readyPRD();

public slots:
    void sendDrv();

};

PRD::PRD(quint8 channelNum,R913V *r913v):chanNum(channelNum),r913v_apd(r913v)
{

    switch (chanNum)
    {
      case 1:
        MS_prd = new ServerSocket("MS_RS_OUT22");
        MS_ready_PRD = new ClientSocket("MS_RS_DRV22",".");
        connect(r913v_apd, SIGNAL(toPRD1()), this, SLOT(sendDrv()));
      break;

      case 2:
        MS_prd = new ServerSocket("MS_RS_OUT23");
        MS_ready_PRD = new ClientSocket("MS_RS_DRV23",".");
        connect(r913v_apd, SIGNAL(toPRD2()), this, SLOT(sendDrv()));
      break;

    }
}

void PRD::run()
{
    while(1) readyPRD();
}

//chanNum=1 для ПРД1, chanNum=2 для ПРД2
void PRD::readyPRD()
{
        memset(&out_KDG[0],0,sizeof(out_KDG));
        memset(&p_KDGR[0],0,sizeof(p_KDGR));
        memset(&Message,0,sizeof(T_Mess913v));
        bytesForTrm.clear();

        result = MS_prd->recData(&bytesForTrm);

        Q_ASSERT(bytesForTrm.size()>0 && bytesForTrm.size()<=(sizeof(MesT_OUT_KDGR)*8));

        if(bytesForTrm.size()>0 && bytesForTrm.size()<=(sizeof(MesT_OUT_KDGR)*8))
        {


     for(qint32 i=0;i<bytesForTrm.size();i++) out_KDG[i] = bytesForTrm.at(i);

   //тут фрагмент с обработкой полученных данных
   //......
   //тут фрагмент с обработкой полученных данных

        quint16 rs = r913v_apd->out_COM_port(&Message.un_mes.outbuf[0],Num_bytes);

        Q_ASSERT(rs==0);

          for (quint32 i=0;i<NumKdg-1;i++)
          {
          memset(&out_kdgr_message,0,sizeof(T_OUT_KDGR_MESSAGE));

          out_kdgr_message.TypeMessage = MES_KDGR_OUT;
          out_kdgr_message.inform.DriverAndTransmitter =
                                    RegOutKdgr[i].Transmitter;
          out_kdgr_message.inform.kdgr.WorkPart = RegOutKdgr[i].Kdgr.WorkPart;
          out_kdgr_message.inform.kdgr.InfPart[0] = RegOutKdgr[i].Kdgr.InfPart[0];
          out_kdgr_message.inform.kdgr.InfPart[1] = RegOutKdgr[i].Kdgr.InfPart[1];
          out_kdgr_message.inform.kdgr.InfPart[2] = RegOutKdgr[i].Kdgr.InfPart[2];


    //здесь запись в UDP-сокет (writeData), о котором речь в core-файлах
          r913v_apd->regMutex.lock();
          r913v_apd->MS_WR_REG->writeData((char*)&out_kdgr_message,sizeof(T_OUT_KDGR_MESSAGE));
          r913v_apd->regMutex.unlock();
          }


    } //if(bytesForTrm.size()>0 && bytesForTrm.size()<=(sizeof(MesT_OUT_KDGR)*8))
}

Получаю вот такие стеки в core-файлах:

Program terminated with signal 11, Segmentation fault.
#0  0x00007f6125347106 in QUdpSocket::writeDatagram(char const*, long long, QHostAddress const&, unsigned short) ()
   from /usr/lib/qt4.8.6/lib/libQtNetwork.so.4
(gdb) bt
#0  0x00007f6125347106 in QUdpSocket::writeDatagram(char const*, long long, QHostAddress const&, unsigned short) ()
   from /usr/lib/qt4.8.6/lib/libQtNetwork.so.4
#1  0x00007f6126244117 in ClientSocket::writeData (this=0x205ba00, data=0x7f611c5b3df0 "\264\004", size=16)
    at /home/user/work/common/trunk/SRC_COMMON/projects/base/rs_udpsocket/rs_udpsocket.cpp:210
#2  0x0000000000406983 in PRD::readyPRD (this=0x7fff0ab9d3a0)
    at /home/user/work/common/trunk/SRC_BM/projects/conf/rs_r913v/r913v.cpp:1825
#3  0x0000000000405cfa in PRD::run (this=0x7fff0ab9d3a0)
    at /home/user/work/common/trunk/SRC_BM/projects/conf/rs_r913v/r913v.cpp:1581
#4  0x00007f6124e1673c in ?? () from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#5  0x00007f6124b6ddb4 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#6  0x00007f61241124fd in clone () from /lib/x86_64-linux-gnu/libc.so.6
#7  0x0000000000000000 in ?? ()
(gdb)

Program terminated with signal 11, Segmentation fault.
#0  0x00007f6e738b25c7 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0  0x00007f6e738b25c7 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007f6e738b4878 in malloc () from /lib/x86_64-linux-gnu/libc.so.6
#2  0x00007f6e74659285 in QString::QString(int, Qt::Initialization) () from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#3  0x00007f6e7474aad1 in ?? () from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#4  0x00007f6e7474ae91 in ?? () from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#5  0x00007f6e7465ef8d in QString::fromAscii_helper(char const*, int) () from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#6  0x00007f6e7465f00e in QString::fromAscii(char const*, int) () from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#7  0x00007f6e75a44ed3 in QDebug::operator<< (this=0x7f6e6bdb1cb0, t=0x7f6e75a4bdeb "Send to ")
    at /usr/lib/qt4.8.6/include/QtCore/qdebug.h:111
#8  0x00007f6e75a41ef4 in ClientSocket::writeData (this=0x2347a20, data=0x7fff8830c9ec "\264\004", size=16)
    at /home/user/work/common/trunk/SRC_COMMON/projects/base/rs_udpsocket/rs_udpsocket.cpp:208
#9  0x0000000000406940 in PRD::readyPRD (this=0x7fff8830c810)
    at /home/user/work/common/trunk/SRC_BM/projects/conf/rs_r913v/r913v.cpp:1825
#10 0x0000000000405c4a in PRD::run (this=0x7fff8830c810)
    at /home/user/work/common/trunk/SRC_BM/projects/conf/rs_r913v/r913v.cpp:1581
#11 0x00007f6e7461473c in ?? () from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#12 0x00007f6e7436bdb4 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#13 0x00007f6e739104fd in clone () from /lib/x86_64-linux-gnu/libc.so.6
#14 0x0000000000000000 in ?? ()
(gdb)

Верхушка стека разнится, хотя ситуация возникает в потоке PRD, в функции writeData (написана на базе QUdpSocket, используется всеми разработчиками, у всех всё ОК). Прогонял свою прогу через valgrind, исправил выданные замечания – не помогло. Выставил в отладочной версии Q_ASSERTы, ни один при вылетах не срабатывает. Выставил mutex`ы на ресурсы, используемые в разных потоках. Просто наблюдал использование памяти в менеджере процессов – данные неизменны на протяжении всего выполнения программы. Исключил writeData из потока PRD – получил такой стек в core:

Program terminated with signal 11, Segmentation fault.
#0  0x00007f839a9a305d in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) ()
   from /usr/lib/qt4.8.6/lib/libQtCore.so.4
(gdb) bt
#0  0x00007f839a9a305d in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) ()
   from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#1  0x00007f839a9cda13 in ?? () from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#2  0x00007f83980a1205 in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#3  0x00007f83980a1538 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#4  0x00007f83980a15f4 in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#5  0x00007f839a9cdbc6 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
   from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#6  0x00007f839a99e23f in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
   from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#7  0x00007f839a99e4c8 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) ()
   from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#8  0x00007f839a9a33a8 in QCoreApplication::exec() () from /usr/lib/qt4.8.6/lib/libQtCore.so.4
#9  0x0000000000406a9a in main (argc=2, argv=0x7fff93dfb418)
    at /home/user/work/common/trunk/SRC_BM/projects/conf/rs_r913v/r913v.cpp:1872
(gdb)

Думается, что в какой-то момент происходит выход за пределы массива, но не догоняю, где..(((


Думается, что в какой-то момент происходит выход за пределы массива, но не догоняю, где..(((

Прогони через Valgrind memcheck. Не умеешь пользоваться? Вот такая проблема думаю разогреет мощный интерес освоить этот инструмент отладки.

I-Love-Microsoft ★★★★★
()

для работы с ком-портами есть штатные классы qt с сигналами, зачем городить свои велосипеды ?

x905 ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Вот я глянул твой код и сразу пришел к выводу - писал студент. Зачем ты работаешь так с потоками в Qt? Зачем усложнил себе жизнь? Работай чисто через сигналы слоты.

Зачем управление памятью в таком режиме? Зачем эти memset-ы. А ты уверен что данных нужное число приходит?

И да, выше правильно говорят - есть QSerialPort...

Я бы такое не пытался отладить, а попробовал переписать с чистого листа с новым вдохновением. Мне часто приходилось писать подобные программы и они ни разу не падали и не глючили, потому что я просто сменил подход. Не знаю, может это с годами придет, это реально что-то такое, что сходу не воспринимается...

I-Love-Microsoft ★★★★★
()
Последнее исправление: I-Love-Microsoft (всего исправлений: 1)

Сдается, в двух потоках производится некорректное взаимодействие с разделяемым ресурсом, на который указывает r913v_apd.

XyAH
()

Подсказка: если написать класс от QObject, а затем moveToThread(&my_thread), где my_thread это тупо QThread без (что важно!) каких-либо собственных доработок, то после my_thread.start() ты будешь обмениваться данными через сигналы-слоты через классы-контейнеры байтов типа QByteArray и забудешь про все эти глюки и падения навсегда.

I-Love-Microsoft ★★★★★
()
Последнее исправление: I-Love-Microsoft (всего исправлений: 1)

Скомпилируй с address sanitizer'ом.

invy ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Топпост не читал, но тут согласен.

Доки Qt, кстати, почему-то как-то довольно бегло по этим вопросам проходят. Сам, помню, с хабра вообще брал https://habrahabr.ru/post/150274/ и до сих пор не знаю, правильно ли делаю :3

jeuta ★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Да вот тоже прихожу к выводу,что через QSerialPort надо действовать. Просто «си-шное» прошлое не отпускает)))) Про moveToThread читал, но тогда не разобрался в вопросе... С memcheck, кстати, гонял, получил замечания про использование неинициализированных переменных, исправил. А выходы за пределы массива, memcheck, как я понял из описания, не обнаруживает? Пробовал ещё через helgrind прогнать, но там вообще темный лес для меня...

В общем, спасибо, ребят, буду переписывать)

Putnik
() автор топика
Ответ на: комментарий от Putnik

А выходы за пределы массива, memcheck, как я понял из описания, не обнаруживает?

Мне всегда казалось что там есть такая возможность, нужно изучить этот вопрос глубже.

I-Love-Microsoft ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.