Bonjour à tous,
Depuis maintenant quelques jours (pour ne pas dire semaines), je me trouve confronté à un problème que je n’arrive pas à résoudre.
En fait, je cherche à développer un programme qui permet de sauvegarder des données qui me sont transmises en UDP. Etant donné que la fréquence d’émission est très importante et des caractéristiques de l’UDP, le cahier des charges m'impose de « découper » mon programme en 2 Threads :
- Le programme principal qui récupère les données en UDP, les met dans un buffer et écrit ces mêmes données dans un QLocalSocket (pipe)
- Un QThread, moins prioritaire que le programme principal et qui tourne en parallèle, qui récupère les données sur le QLocalSocket. Pour la lecture, j’utilise la méthode readLine().
Afin d’éviter les accès concurrents, j’ai mis en place un système de QMutex.
Le problème, c’est que de manière aléatoire (au bout de 2 secondes comme au bout de 10 minutes), je me retrouve avec les erreurs :
- ASSERT failure in QVector<T>::remove: "index out of range".
- QObject::killTimer: timers cannot be stopped from another thread
Sachant que les deux erreurs vont de paire.
Si je ne me trompe pas, la première erreur signifie que j’essaie de supprimer un espace mémoire que je n’ai pas alloué. Et le seul objet qui est susceptible d’utiliser un QVector et qui supprime quelque, c’est le QLocalSocket (lors de la lecture).
Je ne comprends pas forcément la deuxième erreur étant donné que je n'utilise pas de timer ...Je suppose qu'un Timer est associé à la classe QThread. Mais sachant qu'il y a les QMutex, je suppose qu'un QThread ne peut pas arrêter un autre.
Et le debugger de Qt ne me donne aucune information sur la ligne (ou l’objet) qui pose problème.
Voici le constructeur du QThread :
Voici le code de la lecture des données dans le QLocalSocket :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 Thread::Thread(QMutex *p_pipeMutex) { if(NULL != p_pipeMutex) { m_p_pipeMutex = p_pipeMutex; } }
Voici le code de la création du QThread :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 void Thread::run() { while (1) { if (avoirClient == true) // Si QLocalSocket est connecté à un QLocalServer { m_p_pipeMutex->lock(); QByteArray reception; if ((nouveauClient->canReadLine())) // nouveauClient est un QLocalSocket. canReadLine vérifie qu'il y a un caractère '\n'. Les données transmises par trame contiennent toujours ce caractère. { if (nouveauClient->bytesAvailable() > 2048) // Je lis le QLocalSocket seulement si il est rempli un minimum. { reception = nouveauClient->readLine(); compteur = compteur + 1; std::cout << "Reception Thread " << compteur << " : " << reception.data() << std::endl; } } m_p_pipeMutex->unlock(); usleep(500); // Juste histoire de ne pas avoir un affichage qui saccade. }
Voici le code de l'envoi :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 thread = new Thread(&m_pipeMutex); thread->start(QThread::LowPriority);
Donc je me tourne vers vous pour savoir si vous avez déja été confronté à ce type de problème ou si vous avez une solution (ou une idée).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 while (udpSocketTrace->hasPendingDatagrams()) { bufferSimple = new QByteArray; Structure temp; QHostAddress sender; quint16 senderPort; bufferSimple->resize(udpSocketTrace->pendingDatagramSize()); // Resize de la variable qui va récupérer les données udpSocketTrace->readDatagram(bufferSimple->data(), bufferSimple->size(),&sender, &senderPort); // Récupération des données UDP memcpy(temp.texte, bufferSimple->data(), 1024); // Donnée récupérée mise dans une structure memcpy(&bufferTournant[indice], &temp, sizeof(Structure)); // Cette même structure mise dans un buffer m_pipeMutex.lock(); pipe->write(bufferTournant[indice].texte); // Ecriture dans le QLocalSocket m_pipeMutex.unlock(); bufferSimple->clear(); indice = indice + 1; if (indice == 60000) { indice = 0; } }
Merci d'avance pour votre réponse.
Titounet
Partager