J'écris une petite application de loisir en C++ en utilisant Qt. L'application doit lire certains fichiers de dictionnaire au démarrage qui prend un certain temps, donc je créé une classe de fil personnalisé pour analyser les dictionnaires en arrière-plan:Etranges erreurs d'exécution avec une application C++ Qt multithreadée présentant dans le débogueur VS uniquement
class SetupThread : public QThread
{
Q_OBJECT
public:
SetupThread(QObject *p_parent);
void setDictOutputs(WordDictionary *word, KanjiDictionary *kanji, RadicalDictionary *rad);
void run()
{
emit message("Parsing JMdict dictionary...");
m_wordDict->parseDictionary("dictionaries/JMdict_e.xml");
emit message("Parsing KANJIDIC dictionary...");
m_kanjiDict->parseDictionary("dictionaries/kanjidic2.xml");
emit message("Parsing RADKFILEX dictionary...");
m_radDict->parseDictionary("dictionaries/radkfilex.utf8");
}
signals:
void message(const QString &p_msg);
private:
WordDictionary *m_wordDict;
KanjiDictionary *m_kanjiDict;
RadicalDictionary *m_radDict;
};
Les trois classes « Dictionnaire » sont créés par moi et ils ont tous hérite d'une interface commune, qui inclut la fonctionnalité Q_OBJECT pour signaler la classe principale sur la tête du thread d'installation en mode Qt :: QueuedConnection avec des mises à jour de progression lors de l'analyse, afin qu'elle puisse afficher une barre de progression. Le fil de configuration est appelé à partir des principaux constructeur de cours comme celui-ci:
MainForm::MainForm(QWidget *parent, Qt::WFlags flags)
{
/* ... */
m_wordDict = new WordDictionary(this);
m_kanjiDict = new KanjiDictionary(this);
m_radDict = new RadicalDictionary(this);
m_setupThread = new SetupThread(this);
m_setupThread->setDictOutputs(m_wordDict, m_kanjiDict, m_radDict);
m_setupThread->start();
}
j'ai commencé à avoir des problèmes avec l'application s'écraser à la sortie et je ne pouvais pas voir quel était le problème alors j'ai essayé de l'exécuter dans la Le débogueur de Visual C++ 2008. Puis-je obtenir un énorme plantage au démarrage:
exception non gérée à 0x7568b727 dans kanjiflash.exe: exception Microsoft C++: std :: exception à l'emplacement mémoire 0x024ffa1c ..
Les émissions de traces de la pile :
KernelBase.dll 7568b727()
[Cadres ci-dessous peuvent être incorrectes et/ou manquant, pas de symboles chargés pour KernelBase.dll]
KernelBase.dll 7568b727()! msvcr90d.dll! _heap_alloc_dbg_impl (unsigned int nTaille = 72, int nBlockUse = 1, const char * szFileName = 0x00000000, int nLigne = 0, int * errno_tmp = 0x024ff9f8) Ligne 497 + 0xc octets C++
msvcr90d.dll! _nh_malloc_dbg_impl (non signé int nSize = 72, int nhFlag = 0, int nBlockUse = 1, const caractère * szFileName = 0x00000000, int nLine = 0, int * errno_tmp = 0x024ff9f8) Ligne 239 + 0x19 octets C++
msvcr90d.dll! _nh_malloc_dbg (non signé int nSize = 72, int nhFlag = 0, nBlockUse int = 1, const char * szFileName = 0x00000000, int nLine = 0) Ligne 296 + 0x1d octets C++
msvcr90d.dll! malloc (unsigned int nSize = 1) Ligne 56 + 0x15 octets C++
020bea68()
kanjiflash.exe! SetupThread :: run() Ligne 391 + 0x2c octets C++
QtCored4.dll! QThreadPrivate :: start (void * arg = 0x020bd0c8) Ligne 317 C++
msvcr90d.dll! _callthreadstartex() Ligne 348 + 0xf octets C
msvcr90d.dll! _threadstartex (void * PTD = 0x020bd8f0) ligne 331 C
kernel32.dll! 75593677()
ntdll.dll! 77739d72()
ntdll.dll! 77739d45()
La ligne particulière dans SetupThread :: run() cela fait référence est celui où j'essaye d'exécuter parseDictionary ("..."). Cette pile d'appels est obtenue à partir de Windows7 64bit. Dans Windows XP 32 bits, j'ai eu un problème identique, seule différence était que la pile est allée au constructeur d'un QString (const char * ch) de SetupThread :: run(), où il s'est plaint et a montré le tampon * ch à quelques caractères d'ordures.
Maintenant, l'étrange est que cela n'arrive que dans le débogueur. Les deux configurations Debug et Release fonctionnent bien en dehors du débogueur.En tâtonnant avec l'application enquêtant sur ceci, j'ai trouvé et corrigé l'erreur qui m'a fait utiliser le débogueur en premier lieu mais je me demande ce qui se passe réellement et que ferai-je si j'ai besoin d'utiliser le débogueur un jour. Comme je ne suis pas complètement versé dans la programmation multi-thread, je ne suis pas sûr qu'il soit possible de les exécuter dans un débogueur de manière significative, ou peut-être que je fasse quelque chose de mal, comme travailler sur des pointeurs de la classe principale (violation d'accès?). Toute idée grandement appréciée.
difficile à dire sans voir le code utilisé pour arrêter/terminer le thread, mais supposons que votre objet MainForm est supprimé pendant que le thread est encore en cours d'exécution, vous êtes sûr d'avoir des problèmes. En outre, il peut sembler que l'exe fonctionne quand aucun débogueur n'est attaché, alors qu'en fait il se comporte exactement de la même manière mais le problème ne s'affiche pas car certaines fonctionnalités de débogage sont uniquement activées sous le débogueur. – stijn
Le crash mentionne une exception std ::: pouvez-vous entourer votre main et votre thread :: run avec un try catch et voir d'où l'exception est lancée? –
@David: J'ai fait comme vous l'avez suggéré mais mes instructions catch ne semblent pas du tout être exécutées, même avec catch (...), et VS se plaint de "exception non gérée". Un autre mystère. – neuviemeporte