Подскажите пожалуйста.
Написал двупоточную программу для работы с прибором через сетевой интерфейс(UDP пакеты).
Соответственно первый поток интерфейсный, второй непосредственное получение данных.
Под данные выделен один здоровенный массив (40 Мб, больше просто данных никогда не будет).
Структура работы такая после получения данных поток работы с прибором говорит, что принят еще один пакет(или n пакетов) данных,
а интерфейсный поток входит в обработчик таймера(50 мс) и если есть новые пакеты обсчитывает их и выводит на экран.
И все было нормально пока я не дошел до нормального тестирования(суточного). И тут то и выяснилося, что переодически прога падает с сигналом SIGABRT, а в каком месте я понять не могу.
Подскажите как определить в какой функции падает. Проект под QT и под Linux у меня первый. Использую QT Creator 1.2, QT 4.5.3, gcc 4.4.3, Ubuntu 9.04.
Я пробовал через try catch, как бы делал это в студии, но как выяснилось тут они не работают...
В потоках естественно использую QMutex.
Смотрел и дебаг режиме, и через консоль....(выяснилось консоль больше показывает, но стэка функций второго потока добиться не удалось..)
Вот что выдает GDB, как это расшифровать и понять откуда ноги растут?
поддержка полноценных try catch, как я вычитал идет только в версии 4.6, так как там есть поддержка Симбиан которая на них завязана...(могу и ошибаться)
Даже вот такой простой пример у меня не попадает в cath
try{
int a=10;
int b=0;
a/=b;
}
catch(...){
//error
}
также я проверял вылезание за границы выделенной памяти....и нигде в cath не попал. В pro файле config += exceptions прописано.
Так же на одном из форумов я вычитал, что до вышеупомянутой 4.6 к исключениям надо относиться очень аккуратно.
На том же форуме советовали какую-то библиотеку(от третьих лиц), которая сигналы (SIGSEGV, SIGABRT...) переводит в исключения для try catch, но так как под линуксом я без году неделя, то у меня не удалось ее прикрутить.
Если я в чем то ошибаюсь, поправьте меня пожалуйста. Но нигде я не нашел чтобы у кого-нибудь ловились исключения через try catch, у всех с ними только проблеммы.
Если в винде прямо в ядре имееться механизм SEH, который отображаеться в рассширениях MSVC на exception, и ошибки отображаються в пркладной слой в виде exceptions и может быть перехвачена,то в Линухе при ошибках посылаються сигналы(типо SIGABRT) и никаких exceptions не происходит.
2 Skier78rus
Запусти программу под valgrind, он покажет больше информации.
Судя по этому:
Большое спасибо, щас гляну, что это за чудо такое...
поток один или больше?
можна переделать проект под студию и насладиться исключениями
Потоков два....наверное и можно, но он же другие библиотеки будет использовать, или можно прикрутить к студии QT Lib?
да Valgrind мощная штука.....но либо я не разобрался(прочитал статью как использовать), но не в одной ошибке нет моих функции...
он ругаеться на
QApplication a;
в файле main.cpp и эта строчка была создана там автоматически при создании проекта....
правда я только консольную версию пока попробовал, щас с GUI версией разберусь может что и найду....
2 Skier78rus
Ну тогда пора код выкладывать.
Для начала интересно взглянуть на main.cpp
в какой то контейнер одновременно в двух потоках обращаешься (меняешь размер)
Везде исрользуеться QMutex мог конечно налажать где-то, но я две недели уже глюк ищу....
И все что в потоке крутиться(функция не большая) засунул в один большой Мутекс....
код main.cpp
#include....
int main(int argc, char *argv[]){
QApplication a(argc,argv);
MainWindow w;
w.show();
return a.exec();
}
так может обращаешься в потоках с разным кодом (главный и вспомогательный), тогда мютех на функцию потока не поможет
в студии то чего собрать не хочешь?
мне под Линух надо......начальство сказало, что пора осваивать....
Или Вы имеете ввиду только для поиска бага?
Это функция которая вызываеться по таймеру в основном потоке, кроме нее больше ничего не выполняеться(только в главном окне ожидание результата dialog.exec)
void workDlg::timerDataOk(){
try{
qint32 iTmpCountRealiz;
qint32 iTmpReciveSize,tmpMathCount;
qint8 iTmpState,iTmpPrevState;
QString tmpStr,tmpStr1;
double dTmpSin=0,dTmpCos=0;
long double MO=0,DISP=0,MO2=0,dSin=0,dCos=0,POROG=0,dMaxAmpl=0,DISP1=0;
qint16 iMax=-1,iMin=-1,iNumber=0;
QString strMyTime;
myMutex.lock();
iTmpCountRealiz=iCountRealiz;
iTmpReciveSize=iReciveSize;
iTmpState=iState;
iTmpPrevState=iPrevState;
myMutex.unlock();
if(iTmpState==iTmpPrevState && iTmpState!=UNKNOWN_STATE && iTmpPrevState!=UNKNOWN_STATE){
iCountState++;
}
if(iTmpState!=iTmpPrevState){
iCountState=0;
iTmpPrevState=iTmpState;
myMutex.lock();
iPrevState=iTmpPrevState;
myMutex.unlock();
}
if(iCountState==ERROR_COUNT){
bInit=false;
if(iTmpState==CONNECT_SEND){
m_ui->testLabel->setText("Нет ответа от БИЗОНА");
}
else if(iTmpState==PARAM_SEND){
m_ui->testLabel->setText("Ошибка передачи параметров инициализации");
}
else if(iTmpState==START_SEND){
m_ui->testLabel->setText("Ошибка начала получения данных");
}
else if(iTmpState==DATA_RECIVE){
m_ui->testLabel->setText("Ошибка при получения данных");
}
}
tmpMathCount=iCountMathRealiz;
if(SAVE_WORK_DEBUG)
AddDebugFile(fName," In timer");
if( ((iTmpCountRealiz-iCountMathRealiz)>=settingsStruct.soundingStruct.iCount)){//переписать условие добавить было iTmpCountRealiz%settingsStruct.soundingStruct.iCount
if(SAVE_WORK_DEBUG)
AddDebugFile(fName," In if");
while(iCountMathRealiz<(iTmpCountRealiz-iTmpCountRealiz%settingsStruct.soundingStruct.iCount)){
if(SAVE_WORK_DEBUG)
AddDebugFile(fName," In while");
myTime = QTime::currentTime();
strMyTime=myTime.toString("ss:zzz")+" ";
MO=0;
DISP=0;
MO2=0;
if(settingsStruct.soundingStruct.iCount>1){//усреднение если неоходимо
for(qint16 i=DATA_SDVIG;i<iTmpReciveSize-2;i+=4){
dTmpCos=0;
dTmpSin=0;
for(qint16 iC=0;iC<settingsStruct.soundingStruct.iCount;iC++){
dTmpCos+=((reciveBuffer[(iCountMathRealiz+iC)*(iTmpReciveSize)+i+1]<<8)+reciveBuffer[(iCountMathRealiz+iC)*(iTmpReciveSize)+i]);
dTmpSin+=((reciveBuffer[(iCountMathRealiz+iC)*(iTmpReciveSize)+i+2+1]<<8)+reciveBuffer[(iCountMathRealiz+iC)*(iTmpReciveSize)+i+2]);
}
dTmpCos/=settingsStruct.soundingStruct.iCount;
dTmpSin/=settingsStruct.soundingStruct.iCount;
reciveBuffer[iCountMathRealiz*iTmpReciveSize+i]=(qint8)dTmpCos;
reciveBuffer[iCountMathRealiz*iTmpReciveSize+i+1]=(qint8)((qint32)dTmpCos>>8);
reciveBuffer[iCountMathRealiz*iTmpReciveSize+i+2]=(qint8)dTmpSin;
reciveBuffer[iCountMathRealiz*iTmpReciveSize+i+3]=(qint8)((qint32)dTmpSin>>8);
dTmpCos=0;
dTmpSin=0;
}
}
if(SAVE_WORK_DEBUG)
AddDebugFile(fName," Usred");
//*****************MO and DISP********* вся математика
for(qint16 i=DATA_SDVIG;i<iTmpReciveSize-2;i+=4){//
dCos=((reciveBuffer[(iCountMathRealiz)*iTmpReciveSize+i+1]<<8)+reciveBuffer[(iCountMathRealiz)*iTmpReciveSize+i]);
dSin=((reciveBuffer[(iCountMathRealiz)*iTmpReciveSize+i+2+1]<<8)+reciveBuffer[(iCountMathRealiz)*iTmpReciveSize+i+2]);
MO+=sqrt((double)(dSin*dSin+dCos*dCos));
MO2+=(dSin*dSin+dCos*dCos);
}
if(((iTmpReciveSize-8)/4) != 0){
MO/=((iTmpReciveSize-8)/4);///1
DISP1/=((iTmpReciveSize-8)/4);
MO2/=((iTmpReciveSize-8)/4);//130
}
DISP=qAbs(MO2-MO*MO);
POROG=MO+(DISP*settingsStruct.ionogramStruct.fCoeff);
POROG=400;
qint32 iNumData=(quint16)((reciveBuffer[(iCountMathRealiz)*(iTmpReciveSize)+5]<<8)+(quint8)reciveBuffer[(iCountMathRealiz)*(iTmpReciveSize)+4]);
if(SAVE_WORK_DEBUG)
AddDebugFile(fName," MO Disp");
//*********svertka and *********************
for(qint16 i=DATA_SDVIG;i<(iTmpReciveSize-2)-MANIP_SIZE*4;i+=4){
iNumber=(i-DATA_SDVIG)/4;
iConvolutionRe[iNumber]=0;
iConvolutionIm[iNumber]=0;
for(qint16 j=0;j<MANIP_SIZE;j++){
iConvolutionRe[iNumber]+=iManipSignal[j]*((reciveBuffer[(iCountMathRealiz)*iTmpR
eciveSize+i+1+j*4]<<8)+reciveBuffer[(iCountMathRealiz)*iTmpReciveSize+i+j*4]);
iConvolutionIm[iNumber]+=iManipSignal[j]*((reciveBuffer[(iCountMathRealiz)*iTmpR
eciveSize+i+2+1+j*4]<<8)+reciveBuffer[(iCountMathRealiz)*iTmpReciveSize+i+2+j*4]);
}
iConvolutionAmpl[iNumber]=sqrt(iConvolutionRe[iNumber]*iConvolutionRe[iNumber]+i
ConvolutionIm[iNumber]*iConvolutionIm[iNumber]);
if( iConvolutionAmpl[iNumber]>POROG && iMin==-1){
iMin=iNumber;
dMaxAmpl=iConvolutionAmpl[iNumber];
}
if(iMin!=-1){
if(iConvolutionAmpl[iNumber]>dMaxAmpl)
dMaxAmpl=iConvolutionAmpl[iNumber];
}
if(iConvolutionAmpl[iNumber]<POROG && iMin!=-1 && iMax==-1){
iMax=iNumber;
ionStruct.freq[ionStruct.clv]=(settingsStruct.soundingStruct.iStartFreq+settings
Struct.soundingStruct.iStepFreq*(iNumData/settingsStruct.soundingStruct.iCount))*1000;
ionStruct.startHeight[ionStruct.clv]=iMin*1.5+settingsStruct.soundingStruct.iSta
rtHei;
ionStruct.endHeight[ionStruct.clv]=iMax*1.5+settingsStruct.soundingStruct.iStart
Hei;
ionStruct.amp[ionStruct.clv] = dMaxAmpl;
ionStruct.height[ionStruct.clv]=POROG;
ionStruct.clv++;
iMin=-1;
iMax=-1;
dMaxAmpl=0;
}
if(((i+4) >= (iTmpReciveSize-2)-MANIP_SIZE*4) && iMin!=-1){
iMax=iNumber;
ionStruct.freq[ionStruct.clv]=(settingsStruct.soundingStruct.iStartFreq+settings
Struct.soundingStruct.iStepFreq*(iNumData/settingsStruct.soundingStruct.iCount))*1000;
ionStruct.startHeight[ionStruct.clv]=iMin*1.5+settingsStruct.soundingStruct.iSta
rtHei;
ionStruct.endHeight[ionStruct.clv]=iMax*1.5+settingsStruct.soundingStruct.iStart
Hei;
ionStruct.amp[ionStruct.clv] = dMaxAmpl;
ionStruct.height[ionStruct.clv]=POROG;
ionStruct.clv++;
iMin=-1;
iMax=-1;
dMaxAmpl=0;
}
}
//Конец математики
if(SAVE_WORK_DEBUG)
AddDebugFile(fName," Svertka");
iCountMathRealiz+=settingsStruct.soundingStruct.iCount;//
tmpStr="Полученике данных: ";
tmpStr1.setNum(iCountMathRealiz);
tmpStr+=tmpStr1;
m_ui->testLabel->setText(tmpStr);
}
}//if %
if(iCountMathRealiz!=tmpMathCount){//если что-то обсчитал, то вывод на экран
m_ui->ciFrame->update();
}
if(!bStartUdp && !bInit /*&& (iCountMathRealiz == (iTmpCountRealiz) || iCountState==ERROR_COUNT)*/){//Проверка пора ли закончить или нет
m_ui->ciFrame->update();
mathTimer->stop();
if(myThread.isRunning()){
myThread.stop();
myThread.wait();
}
if(ionStruct.clv!=0)
saveIonFile();
m_ui->rEdit->setText(aaa);
if( iCountState==0)
m_ui->testLabel->setText("БИЗОН остановлен");
else
m_ui->testLabel->setText("БИЗОН остановлен c ошибкой");
iCountState=0;
if(IS_SOURCE_SAVE){
QFile file("SourceData.DAT");
if(!file.open(QIODevice::WriteOnly)){
}
else{
QString fStr,fStr1;
for(qint16 i=0;i<iTmpCountRealiz;i++){
fStr="Realiz № ";
fStr1.setNum(i+1);
fStr+=fStr1+'\n';
file.write(fStr.toLocal8Bit());
for(qint16 j=DATA_SDVIG;j<iTmpReciveSize-2;j+=4){
fStr="";
fStr.setNum((j-DATA_SDVIG)/4);
dCos=((reciveBuffer[(i)*iTmpReciveSize+j+1]<<8)+reciveBuffer[(i)*iTmpReciveSize+j]);
fStr1.setNum((qint32)dCos);
fStr+='\t'+fStr1+'\t';
dSin=((reciveBuffer[(i)*iTmpReciveSize+j+2+1]<<8)+reciveBuffer[(i)*iTmpReciveSize+j+2]);
fStr1.setNum((qint32)dSin);
fStr+=fStr1+'\n';
file.write(fStr.toLocal8Bit());
}
}
file.close();
}
}
iCountState=0;
}
if(bStartUdp){//начало всей работы
m_ui->ciFrame->update();
bStartUdp=false;
if(!IS_TIMER_EMULATION){//need ! !!!!!!!!!!!!!!!!!!!!!!!!!!!
if(myThread.isRunning()){
myThread.stop();
myThread.wait();
}
myThread.start(QThread::HighPriority);//QThread::NormalPriority TimeCriticalPriority
}
else{
iState=CONNECT_SEND;
bInit=true;
emulationTimer->start(1000/settingsStruct.soundingStruct.iPulseFreq);
}
m_ui->testLabel->setText("Соединение с БИЗОНОМ");
}
if(SAVE_WORK_DEBUG)
AddDebugFile(fName," End");
}
catch(...){
m_ui->testLabel->setText("Ошибка обработки даных!!!!!!!!!!!");
}
}
void GetDataThread::run(){
QByteArray bArray;
QHostAddress hAddress;
qint16 iPort;
qint32 iTmpCountRealiz,iTmpReciveSize;
QString strMyTime=thTime.toString("ss:zzz")+" ";
QHostAddress sender;
quint16 senderPort;
quint16 tmp;
QString strPriv="";
char toSend[100];
QString text,text1;
quint16 iTmp=0;
QTime myTime;
qint16 tmpSig=0;
quint8 iSdvig;
qint64 iRSize=-1;
QString fName="1thread.dat";
ResetDebugFile(fName);
//AddDebugFile(fName," In Thread");
bInit=true;
myMutex.lock();
iState=CONNECT_SEND;
iPrevState=CONNECT_SEND;
hAddress=QHostAddress(settingsStruct.connectStruct.strAddress);
iPort=settingsStruct.connectStruct.iPort;
myMutex.unlock();
bArray.clear();
bArray[0]=0xA0;
udpSocket->writeDatagram(bArray.data(), bArray.size(),hAddress,iPort);
while(!stoped){
if(!IS_EMULATION){
myMutex.lock();
iTmpCountRealiz=iCountRealiz;
myMutex.unlock();
while (udpSocket->hasPendingDatagrams() && (iTmpCountRealiz < (settingsStruct.soundingStruct.iCountFreq*settingsStruct.soundingStruct.iCoun
t)) ) {
myMutex.lock();
thTime = QTime::currentTime();
iTmpReciveSize=udpSocket->pendingDatagramSize();//4000;
iRSize=udpSocket->readDatagram(reciveBuffer+(iTmpCountRealiz*iMathReciveSize),udpSocket->pendingDatagramSize(),&sender,&senderPort);//вставил iMathReciveSize
if(iRSize!=-1){
if(reciveBuffer[iTmpCountRealiz*iMathReciveSize]== (char)0xB0){
bInit=true;
for(int i=1;i<iMathReciveSize-2;i++){
strPriv+=reciveBuffer[iTmpCountRealiz*iMathReciveSize+i];
}
if(true/*(quint8)reciveBuffer[iTmpCountRealiz*iMathReciveSize+24]==3 || (quint8)reciveBuffer[iTmpCountRealiz*iMathReciveSize+24]==7*/){
//m_ui->testLabel->setText(strPriv);
toSend[0]=0xA1;
toSend[2]=(qint8)(((settingsStruct.soundingStruct.iStartFreq)>>8));
toSend[1]=(qint8)(settingsStruct.soundingStruct.iStartFreq);
toSend[4]=(qint8)((settingsStruct.soundingStruct.iEndFreq)>>8);
toSend[3]=(qint8)((settingsStruct.soundingStruct.iEndFreq));
toSend[6]=(qint8)((settingsStruct.soundingStruct.iStepFreq)>>8);
toSend[5]=(qint8)((settingsStruct.soundingStruct.iStepFreq));
toSend[8]=(qint8)(settingsStruct.soundingStruct.iStartHei>>8);
toSend[7]=(qint8)(settingsStruct.soundingStruct.iStartHei);
toSend[10]=(qint8)(settingsStruct.soundingStruct.iEndHei>>8);
toSend[9]=(qint8)(settingsStruct.soundingStruct.iEndHei);
toSend[11]=(qint8)(100/settingsStruct.soundingStruct.iPulseFreq);
toSend[12]=(qint8)(settingsStruct.soundingStruct.iCount);
toSend[13]=(qint8)(settingsStruct.soundingStruct.iManipCode);
tmp=(settingsStruct.soundingStruct.iStartHei*2*10000)/300000;
udpSocket->writeDatagram(toSend, 14,QHostAddress(settingsStruct.connectStruct.strAddress),settingsStruct.connectS
truct.iPort);
iState=PARAM_SEND;
}
else{
bInit=false;
}
}
else if(reciveBuffer[iTmpCountRealiz*iMathReciveSize]== (char)0xB3){
toSend[0]=0xA2;
udpSocket->writeDatagram(toSend,1,QHostAddress(settingsStruct.connectStruct.strAddress),
settingsStruct.connectStruct.iPort);
iState=START_SEND;
}
else if(reciveBuffer[iTmpCountRealiz*iMathReciveSize]==(char) 0xB1){//При полученииданных всегда попадаем сюда
iState=DATA_RECIVE;
PrevState=DATA_ERROR;
iTmpCountRealiz++;
if(iMathReciveSize!=iTmpReciveSize)//???????????????????????????????or do exit????????????
iTmpReciveSize=iMathReciveSize;
if(iTmpCountRealiz ==(settingsStruct.soundingStruct.iCountFreq*settingsStruct.soundingStruct.iCoun
t
)){
toSend[0]=0xA3;
udpSocket->writeDatagram(toSend,1,QHostAddress(settingsStruct.connectStruct.strAddress),
settingsStruct.connectStruct.iPort);
iState=UNKNOWN_STATE;
bInit=false;
}
}
}//if iRSize
else{
AddDebugFile(fName," ErrorRecive Data");
}
iReciveSize=iTmpReciveSize;
iCountRealiz=iTmpCountRealiz;
msleep(1);
}
msleep(1);
}
else{//Это эмуляция прибора с ней ни одного сбоя не поймал
myMutex.lock();
iState=CONNECT_SEND;
if((iState==CONNECT_SEND || iState==DATA_RECIVE)&& iCountRealiz<settingsStruct.soundingStruct.iCountFreq*settingsStruct.soundingStruct.iCoun
t
){
iSdvig=(iCountRealiz/settingsStruct.soundingStruct.iCount);//(iMathReciveSize-8)/16;//(iMathReciveSize-8)/4-MANIP_SIZE*2;//iCountRealiz*3;
reciveBuffer[iCountRealiz*iMathReciveSize]=0XB1;
reciveBuffer[iCountRealiz*iMathReciveSize+4]=(qint8)(iCountRealiz);
reciveBuffer[iCountRealiz*iMathReciveSize+5]=(qint8)((iCountRealiz)>>8);
for(qint16 k=DATA_SDVIG;k<iMathReciveSize*2-2;k+=4){
tmpSig=10+10*sin(2*3.14*(k-6)*5/(4*50));
reciveBuffer[iCountRealiz*iMathReciveSize+k]=(qint8)tmpSig;
reciveBuffer[iCountRealiz*iMathReciveSize+k+1]=(qint8)(tmpSig>>8);
reciveBuffer[iCountRealiz*iMathReciveSize+k+2]=(qint8)tmpSig;
reciveBuffer[iCountRealiz*iMathReciveSize+k+3]=(qint8)(tmpSig>>8);
}
iCountRealiz++;
iReciveSize=iMathReciveSize;
iState=DATA_RECIVE;
iPrevState=DATA_ERROR;
}
else if(iCountRealiz>=settingsStruct.soundingStruct.iCountFreq*settingsStruct.soundingStruct.iCou
n
t){
iState=UNKNOWN_STATE;
bInit=false;
}
myMutex.unlock();
msleep(1);
}
}
bInit=false;
stoped=false;
}
Про код соглашусь......
Я просто поудалял, там есть функция AddDebugFile, пытался по ней невышло.....
Там с постом какая-то проблема,надо нижние два раскрывающиеся тексты смотреть.....
А как qt к студии прикрутить?
Skier78rus, смотри http://www.forum.crossplatform.ru/index.php?showtopic=1455. код читать в виде простого текста тяжело.
Почитай про сигналы и их обработку в linux:
man signal
Сейчас нет возможности посмотреть исходники, думаю завтра получиться, но рекомендую добавить функции подробного логирования (хорошо помогает отлаживать такие ошибки).
Спасибо.
Прочитал про сигналы, поправьте, если я ошибаюсь, но есть два типа сигналов, первые это сигналы QT, которые легко перехватываються и обрабатываються.
И второй тип это сигналы ядра Linux, типо SIGABRT, которые тоже можно самому перехватить, но я не понял как....
А функции подробного логирования это qDebug и тому подобное из библиотеки TestLib???
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)