Programme plante seulement la version build — comment déboguer?
J'ai un "Chat de Schroedinger" type de problème ici -- mon programme (en fait de la suite de test pour mon programme, mais un programme d'ailleurs) est en panne, mais seulement lors de sa construction en mode release, et seulement lorsqu'il est lancé à partir de la ligne de commande. Par le biais de l'homme des cavernes de débogage (c'est à dire, méchant printf() messages dans tous les sens), j'ai déterminé la méthode de test où le code est en panne, mais malheureusement, la réelle crash semble se produire dans certains destructeur, depuis la dernière trace des messages je vois dans d'autres destructeurs qui exécuter proprement.
Lorsque je tente de l'exécuter ce programme à l'intérieur de Visual Studio, il ne plante pas. En va de même lors du lancement de WinDbg.exe. Le blocage se produit uniquement lors du lancement de la ligne de commande. Ce qui se passe sous Windows Vista, btw, et, malheureusement, je n'ai pas accès à une machine XP dès maintenant pour tester.
Il serait vraiment bien si je pouvais obtenir Windows pour imprimer une trace de la pile, ou quelque chose autres que de simplement terminer le programme comme si elle avait quitté proprement. Quelqu'un aurait-il des conseils sur comment je pourrais obtenir plus de renseignements utiles ici et nous espérons résoudre ce bug?
Edit: Le problème a effectivement été causé par un hors des limites d'un tableau, que je décrirai plus dans ce post. Merci à tous pour votre aide dans la recherche de ce problème!
- Pouvez-vous donner un exemple de cette méthode de test?
- Non désolé, le code est beaucoup trop complexe pour être facilement coller ici, et comme je l'ai mentionné, il n'est pas le cas dans la méthode d'essai lui-même, mais plutôt un destructeur par la suite. Il n'y a pas de pointeurs non initialisés ou quelque chose comme ça dans cette méthode, bien que.
- La plupart des réponses ne sont guère plus que des suppositions. Il existe quelques techniques pour l'analyse de s'écraser les versions release sans y attacher un débogueur: stackoverflow.com/a/18513077/214777?stw=2
- C'est peut-être pas de votre faute: Est l'optimisation de niveau -O3 dangereux dans g++?
Vous devez vous connecter pour publier un commentaire.
Dans 100% des cas que j'ai vu ou entendu parler de, où un programme C ou C++ fonctionne très bien dans le débogueur, mais échoue lors de l'exécution à l'extérieur, la cause a été écrit après la fin d'une fonction locale de tableau. (Le débogueur met plus sur la pile, de sorte que vous êtes moins susceptibles de remplacer quelque chose d'important.)
Lorsque j'ai rencontré des problèmes de ce genre auparavant, il a été généralement en raison de l'initialisation d'une variable. En mode debug, les variables et pointeurs sont initialisées à zéro automatiquement, mais en mode release, ils ne le font pas. Par conséquent, si vous avez un code comme ceci
En mode debug, le code dans le si n'est pas exécuté, mais en mode release, p contient une valeur non définie, ce qui est peu probable 0, donc le code est exécuté souvent provoquer un incident.
Je voudrais vérifier votre code pour les variables non initialisées. Cela peut également s'appliquer au contenu des tableaux.
Pas de réponse jusqu'à présent, a essayé de donner un sérieux aperçu sur les techniques disponibles pour le débogage des applications à libération:
Release et Debug de se comporter différemment pour de nombreuses raisons. Voici un excellent aperçu. Chacun de ces différences pourrait causer un bug dans la version Release qui n'existe pas dans la version Debug.
La présence d'un débogueur peut modifier le comportement d'un programme trop, à la fois pour la release et debug. Voir cette réponse. En bref, au moins le Débogueur Visual Studio utilise le Débogage Tas automatiquement lorsqu'il est connecté à un programme. Vous pouvez activer le débogage tas en utilisant la variable d'environnement _NO_DEBUG_HEAP . Vous pouvez spécifier ce soit dans vos propriétés de l'ordinateur, ou dans les Paramètres du Projet dans Visual Studio. Que peut faire le crash reproductible avec le débogueur.
Plus sur le débogage des tas de corruption.
Si la solution précédente ne fonctionne pas, vous avez besoin pour attraper l'exception non gérée et joindre un post-mortem débogueur l'instance de la collision. Vous pouvez utiliser, par exemple, WinDbg pour cela, les détails sur la avaiable post-mortem des débogueurs et leur installation sur le site MSDN
Vous pouvez améliorer votre code de gestion des exceptions et si ce est une application de production, vous devez:
un. Installation d'un custom de résiliation à l'aide de gestionnaire de
std::set_terminate
Si vous souhaitez déboguer ce problème localement, vous pouvez exécuter une boucle sans fin à l'intérieur de la résiliation de gestionnaire et de sortie du texte à la console pour vous informer que
std::terminate
a été appelé. Ensuite attacher le débogueur et vérifier la pile des appels. Ou vous imprimer la trace de la pile comme décrit dans cette réponse.Dans une application de production, vous pourriez envoyer un rapport d'erreurs de retour à la maison, idéalement avec un petit vidage de la mémoire, qui permet d'analyser le problème, comme décrit ici.
b. Utilisation de Microsoft gestion structurée des exceptions mécanisme qui vous permet d'attraper les exceptions matérielles et logicielles. Voir MSDN. Vous pourriez garde parties de votre code à l'aide de la SEH et d'utiliser la même approche que dans une) pour déboguer le problème. SEH donne plus d'informations sur l'exception qui s'est produite que vous pouvez utiliser lors de l'envoi d'un rapport d'erreur à partir d'une production de l'app.
Choses à regarder dehors pour:
Tableau des dépassements - le débogueur visual studio inserts de rembourrage qui peut cesser se bloque.
Conditions de course - avez-vous plusieurs threads concernés si une condition de course de nombreux ne se montre que lorsqu'une application est exécutée directement.
De liens - est votre communiqué de construire en tirant dans les bonnes bibliothèques.
Choses à essayer:
Minidump - vraiment facile à utiliser (il suffit de le rechercher dans msdn) vous donne plein de vidage sur incident pour chaque thread. Vous venez de charger la sortie dans visual studio et c'est comme si vous étiez le débogage au moment de l'accident.
Vous pouvez définir WinDbg comme votre débogueur post-mortem. Cela permettra de lancer le débogueur et le joindre à la procédure lorsque l'incident se produit. Pour installer WinDbg pour le post-mortem de débogage, utilisez l'option /I (remarque c'est capitalisés):
Plus de détails ici.
Quant à la cause, il est le plus probablement une variable non initialisé comme les autres réponses suggèrent.
Après de nombreuses heures de débogage, j'ai enfin trouvé la cause du problème, ce qui a effectivement été causé par un dépassement de la mémoire tampon, a provoqué un octet unique différence:
C'est un fencepost erreur (off-par-une erreur) et a été corrigé par:
La chose étrange est, j'ai mis plusieurs appels à _CrtCheckMemory (ne) autour de différentes parties de mon code, et ils revenaient toujours 1. J'ai été en mesure de trouver la source du problème en plaçant "return false;" appels dans le cas du test, et puis finalement se déterminer par essais et erreurs où la faute a été.
Merci à tous pour vos commentaires -- j'ai appris beaucoup de choses sur windbg.exe dès aujourd'hui! 🙂
Même si vous avez construit votre exe comme une libération, vous pouvez toujours générer des PDB (base de données du Programme) les fichiers qui vous permettra de trace de la pile et faire une quantité limitée de l'inspection des variables.
Dans vos paramètres de construction il y a une option pour créer les fichiers PDB. Activez cette fonction et de rétablir le lien. Puis essayez d'exécuter à partir de l'IDE d'abord pour voir si vous obtenez le crash. Si oui, alors la grande - vous êtes tous ensemble pour regarder les choses. Si non, puis lors de l'exécution de la ligne de commande, vous pouvez le faire de deux choses l'une:
Quand on lui demande de pointer vers des fichiers PDB, parcourir les trouver. Si l'APB ont été mis dans le même dossier que votre fichier EXE ou DLL, ils seront probablement ramassé automatiquement.
L'APB est de fournir un lien vers la source avec suffisamment d'informations de symbole pour le rendre possible de voir les traces de pile, variables etc. Vous pouvez inspecter les valeurs normales, mais sachez que vous pouvez obtenir de fausses lectures que l'optimisation passe peut signifier que les choses n'apparaissent dans les registres, ou des choses se produire dans un ordre différent de celui que vous attendez.
NB: je suis en supposant un Windows/environnement Visual Studio ici.
Accidents de ce genre sont presque toujours causés en raison d'un IDE est généralement réglé le contenu de la variable non initialisée à zéros, null, ou quelque autre "raisonnable" de la valeur, alors que lors de l'exécution en mode natif, vous obtiendrez quelque soit aléatoire ordures que le système de ramasse.
Votre erreur est donc presque certainement que vous êtes en utilisant quelque chose comme vous utilisez un pointeur avant il a été initialisé correctement et vous avez de s'en sortir avec elle dans l'IDE, car il n'est pas n'importe où, dangereuses ou la valeur est gérée par votre contrôle d'erreur - mais en mode release, il fait quelque chose de méchant.
Afin d'avoir un crash dump que vous pouvez analyser:
Vous devriez également vérifier les outils de Les outils de débogage pour windows.
Vous pouvez surveiller l'application et de voir toutes les exceptions de première chance qui étaient avant votre deuxième chance exception.
Espère que ça aide...
Une fois j'ai eu un problème lors de l'application s'est comporté de la même manière à la vôtre. Il s'est avéré être un méchant de dépassement de mémoire tampon dans sprintf. Naturellement, il a travaillé lors de l'exécution avec un débogueur. Ce que j'ai fait, était d'installer une exception non gérée du filtre (SetUnhandledExceptionFilter) dans laquelle j'ai simplement bloqué à l'infini (à l'aide de WaitForSingleObject sur un faux poignée avec une valeur de délai d'expiration de l'INFINI).
De sorte que vous pourriez quelque chose le long des lignes de:
J'ai ensuite attaché le débogueur après le bug avait manifesté de lui-même (gui programme a cessé de répondre).
Ensuite, vous pouvez soit prendre un cliché et de travailler avec elle plus tard:
Ou le corriger tout de suite. La façon la plus simple est de suivre où processeur de contexte a été enregistré par le runtime exception de la manipulation de machines:
Commande de recherche de la pile l'adresse de l'espace pour l'enregistrement du CONTEXTE(s) à condition que la longueur de la recherche. J'ai l'habitude d'utiliser quelque chose comme 'l?10000'. Remarque, ne pas utiliser de unsually grand nombre que l'enregistrement que vous êtes après, généralement à proximité de la unhanded exception cadre du filtre.
1003f est la combinaison d'indicateurs (je crois qu'il correspond à CONTEXT_FULL) utilisé pour capturer le processeur de l'état.
Votre recherche devrait ressembler à ceci:
Une fois que vous obtenez les résultats, utiliser l'adresse de la rx des poumons de commande:
Cela vous mènera à ce nouveau CONTEXTE, exactement au moment de la collision (vous obtenez exactement la trace de la pile au moment de votre application s'est écrasé).
En outre, l'utilisation:
pour savoir exactement où l'exception a eu lieu.
Espère que cela aide.
Parfois, cela arrive parce que vous avez enveloppé opération importante à l'intérieur de "faire valoir" de la macro. Comme vous le savez peut-être, "d'affirmer" évalue les expressions que sur le mode de débogage.
À l'égard de vos problèmes pour obtenir des informations de diagnostic, avez-vous essayé d'utiliser adplus.vbs comme une alternative à WinDbg.exe? Pour l'attacher à un processus en cours d'exécution, utilisez
Ou pour démarrer l'application dans le cas où l'incident se produit rapidement:
Plein d'infos sur adplus.vbs peut être trouvé à: http://support.microsoft.com/kb/286350
Ntdll.dll avec le débogueur
Un peu de savoir la différence entre le lancement d'un programme à partir de l'IDE ou WinDbg plutôt que de le lancer en ligne de commande /de bureau, c'est que lors du lancement avec un débogueur (c'est à dire IDE ou WinDbg) ntdll.dll utilise un autre segment de la mise en œuvre qui effectue un peu de la validation sur la mémoire de l'allocation/libération.
Vous pouvez lire des informations pertinentes dans inattendu de l'utilisateur point d'arrêt dans ntdll.dll. Un outil qui pourrait être en mesure pour vous aider à identifier le problème, c'est PageHeap.exe.
D'analyse des incidents
Vous n'avez pas à écrire, qu'est-ce que le "crash" vous rencontrez. Une fois que le programme se bloque et vous propose d'envoyer les informations d'erreur à Microsoft, vous devriez être en mesure de cliquer sur les techniques de l'information et de cocher au moins le code d'exception, et avec un peu d'effort, vous pouvez même effectuer des analyses post-mortem (voir Heisenbug: WinApi programme se bloque sur certains ordinateurs) pour les instructions)
Vista SP1 a fait un vraiment agréable de vidage sur incident générateur intégré dans le système. Malheureusement, il n'est pas activé par défaut!
Voir cet article:
http://msdn.microsoft.com/en-us/library/bb787181(SV.85).aspx
L'avantage de cette approche est qu'aucun logiciel supplémentaire ne doit être installé sur le système affecté. Poignée et déchirer, bébé!
Que mon expérience, qui sont pour la plupart des problèmes de corruption de mémoire.
Par exemple :
il est très possible d'être normal en mode de débogage lorsque l'on exécute le code.
Mais dans libération, qui serait/pourrait être crash.
Pour moi, pour fouiller là où la mémoire est hors limite est trop pénible.
Utiliser certains outils comme Visual Détecteur De Fuite (windows) ou valgrind (linux) sont plus sages choix.
Une excellente façon de déboguer une erreur de ce genre est de permettre des optimisations pour votre version de débogage.
J'ai vu beaucoup de bonnes réponses. Cependant, il n'en est aucun qui m'ont aidé. Dans mon cas, il y a une mauvaise utilisation de la les instructions SSE avec le non alignés mémoire. Jetez un oeil à votre bibliothèque de mathématiques (si vous en utilisez un), et essayez de désactiver SIMD de soutien, de recompiler et de reproduire l'incident.
Exemple:
D'un projet inclut mathfu, et utilise les classes avec vecteur STL: std::vector< mathfu::vec2 >. Une telle utilisation sera probablement provoquer un plantage au moment de la construction de mathfu::vec2 point depuis la STL par défaut de l'allocateur ne garantit pas nécessaire de 16 octets de l'alignement. Dans ce cas de prouver l'idée, on peut définir
#define MATHFU_COMPILE_WITHOUT_SIMD_SUPPORT 1
avant chaque incluent des mathfu, recompiler, dans la Version de configuration et vérifiez de nouveau.La Debug et RelWithDebInfo configurations a bien fonctionné pour mon projet, mais pas le Libération un. La raison de ce comportement est probablement parce que le débogueur processus d'allocation/désallocation de demandes et fait de la mémoire de la comptabilité de contrôler et de vérifier les accès à la mémoire.
J'ai vécu la situation dans Visual Studio 2015 et 2017 environnements.
Quelque chose de semblable dans les parages pour moi une fois avec GCC. Il s'est avéré être un trop agressives d'optimisation qui a été activé uniquement lors de la création de la version finale et non pas pendant le processus de développement.
Bien, pour dire la vérité, il en était de ma faute, pas de gcc, comme je n'avais pas remarqué que mon code a été en s'appuyant sur le fait que cette optimisation n'aurait pas été fait.
Il m'a fallu beaucoup de temps pour remonter et je l'ai seulement parce que j'ai demandé sur un forum et que quelqu'un me l'a fait penser. Alors, permettez-moi de retourner la faveur, juste au cas où cela vous arrive aussi.
J'ai trouvé cette cet article utile pour votre scénario. ISTR les options du compilateur ont été un peu hors de date. Regardez autour de votre projet Visual Studio options pour voir comment générer des fichiers pdb pour votre version de construire, etc.
C'est suspect que cela allait se produire en dehors du débogueur et pas à l'intérieur; cours d'exécution dans le débogueur n'est normalement pas changer le comportement de l'application. Je voudrais vérifier l'environnement de différences entre la console et l'IDE. Aussi, évidemment, de compiler version sans optimisations et avec les informations de débogage, et de voir si cela influe sur le comportement. Enfin, le post-mortem des outils de débogage d'autres personnes ont suggéré ici, vous pouvez généralement obtenir des indices d'eux.
De débogage release peut être une douleur grâce à l'optimisation de changer l'ordre dans lequel les lignes de votre code semble être exécutée. Il peut vraiment prêter à confusion!
Une technique pour au moins réduire le problème est d'utiliser MessageBox() pour l'affichage rapide des déclarations indiquant quelle partie du programme de votre code a obtenu d' ("Démarrage de Foo()", "Démarrage de Foo2()"); commencer à les mettre en haut de fonctions dans le domaine de votre code que vous pensez (que faisiez-vous au moment où il s'est écrasé?). Quand vous pouvez dire qui de fonction, modifiez les boîtes de message à des blocs de code ou même des lignes individuelles dans cette fonction jusqu'à ce que vous réduire à quelques lignes. Ensuite, vous pouvez lancer l'impression de la valeur des variables pour voir dans quel état ils sont sur le point de s'écraser.
Essayez d'utiliser _CrtCheckMemory() pour voir quel est l'état de la mémoire allouée est dans .
Si tout va bien , _CrtCheckMemory retourne VRAI , d'autre FAUX .
Vous pouvez exécuter votre logiciel avec des indicateurs Globaux activé (voir dans les Outils de Débogage pour Windows). Il va très souvent de l'aide de l'ongle le problème.
Faire de votre programme de générer un mini dump lorsque l'exception se produit, puis l'ouvrir dans un débogueur (par exemple, dans WinDbg). Les fonctions de la touche à regarder: MiniDumpWriteDump, SetUnhandledExceptionFilter
Voici un cas, j'ai eu que quelqu'un pourrait trouver instructif. Il ne s'est écrasé dans la version de Qt Creator - pas en debug. J'ai été en utilisant .les fichiers ini (que je préfère les applications qui peuvent être copiés sur d'autres lecteurs, par rapport à ceux qui perdent leurs paramètres si le Registre est corrompu). Cela s'applique à toutes les applications qui stockent leurs paramètres dans les applications' arborescence de répertoire. Si le debug et release sont sous répertoires différents, vous pouvez avoir un réglage différent entre eux, trop. J'ai eu la préférence vérifié dans l'un qui n'a pas été vérifié dans les autres. Il s'est avéré être la source de mon accident. Bonne chose, je l'ai trouvé.
Je déteste dire ça, mais je ne l'ai diagnostiqué la panne en MS Visual Studio Community Edition; après avoir VS installé, laissant mon appli crash dans Qt Creator, et choisir de l'ouvrir dans de Visual Studio débogueur. Alors que mon application Qt avait pas de symbole info, il s'avère que les bibliothèques Qt a quelques. Elle m'a amené à la ligne incriminée; depuis que j'ai pu voir quelle méthode a été appelée. (Encore, je pense que Qt est une pratique, puissant, & croix-plate-forme LGPL cadre.)
J'ai eu cette erreur et vs s'est écrasé, même lorsque vous essayez de !nettoyer! mon projet. Alors j'ai supprimé les fichiers obj manuellement à partir du répertoire de sortie, et après qu'elle construit très bien.
Je suis d'accord avec Rolf. Parce que la reproductibilité est donc important, vous ne devriez pas avoir un mode débogage non. Toutes vos constructions doivent être debuggable. Ayant deux objectifs à déboguer plus que doubler le débogage de charge. Juste navire le "debug mode" version, sauf si elle est inutilisable. Dans ce cas, le rendre utilisable.