J'ai une application C ++ qui enveloppe de grandes parties du code dans les blocs. Lorsque je saisie des exceptions, je peux retourner l'utilisateur à un état stable, ce qui est agréable. Mais je ne reçois plus de décharges. J'aimerais vraiment comprendre où dans le code l'exception a lieu, je peux donc la connecter et le réparer. p>
Être capable d'obtenir une décharge sans arrêter l'application serait idéale, mais je ne suis pas sûr que ce soit possible. P>
Y a-t-il une manière que je puisse comprendre où l'exception a été lancée à l'intérieur du bloc de capture? Si c'est utile, j'utilise MSVC ++ natif sur Windows XP et plus élevé. Mon plan consiste simplement à enregistrer les accidents dans un fichier sur les machines des différents utilisateurs, puis téléchargez les crashlogs une fois qu'ils arrivent à une certaine taille. P>
5 Réponses :
Ce dont vous avez besoin est d'analyser la pile pour déterminer l'exception de l'exception. Pour MSVC, il y a une libernelle appelée dbghelp.dll A> Cela peut vous aider à vous déconnecter des exceptions. En général, ce que je fais, c'est de vous déconnecter un Fichier MiniDump et utilisez ceci pour rejouer le problème < / a> à côté de l'utilisation de la bonne base de données de programmes (fichier PDB). Cela fonctionne sur un système client qui ne vient pas avec code source ou à qui vous ne voudrez pas donner de PDBS. P>
Vous pouvez écrire des vidages à l'aide de MiniDumpwirshump fonction. p>
Si vous utilisez des exceptions C ++, vous pouvez simplement inclure les informations de fichier / ligne / fonction (vous le verrez donc comme texte si vous appelez std :: Exception.Que ()) Dans n'importe quel endroit où vous lancez exception (en utilisant ____Fonction____, ____File____ et ____line____ macros). p>
Si vous essayez d'attraper des exceptions du système d'exploitation, alors écrasez l'application sera probablement un meilleur choix. P>
Ceci est possible avec l'utilisation de SEH (manipulation de l'exception structurée). Le point est que MSVC implémente les exceptions c ++ via SEH. D'autre part, le SEH pur est beaucoup plus puissant et flexible.
C'est ce que vous devriez faire. Au lieu d'utiliser des blocs PURE C ++ ESSAY / CATTENNES comme celui-ci: P>
void DoSomething() { __try { DoSomethingInner(); } __except (DumpExc(GetExceptionInformation()), EXCEPTION_CONTINUE_SEARCH) { // never get there } } void DumpEx(EXCEPTION_POINTERS* pExc) { // Call MiniDumpWriteDump to produce the needed dump file }
Utiliser SEH directement est OK si vous vous souciez de la portabilité. Les exceptions standard C ++ sont plus portables (puits, à l'exception de plusieurs compilateurs pour systèmes embarqués qui ne prennent pas en charge les exceptions).
C'est un moyen efficace de gérer les exceptions c ++. Si vous souhaitez obtenir des informations utiles sur les exceptions du système d'exploitation, telles que le débordement de la pile ou la violation d'accès, vous devez organiser un MiniDumpwriDeDmp code> à appeler à partir d'un autre processus.
@George: Il n'y a actuellement aucun moyen portable pour obtenir des traces de pile en C ++. Je semble rappeler que c'est une situation que la nouvelle norme C ++ 0X tente d'améliorer.
Pas nécessairement. Eh bien, si vous parlez de débordement de pile et que vous gérez cette exception avant que la pile ne se déroule - vous devriez appeler «MiniDumpwridressump» d'un autre fil (puisque notre thread n'a presque pas de pile). Mais il n'y a pas besoin de faire des choses d'un autre processus. Sauf si vous envisagez l'exception en tant que bogue, et ne vous appuyez pas sur ce processus
@BEN VOIGT: C'est surtout vrai (il existe des méthodes pour ce faire qui fonctionnent correctement pour Win32 W / Mingw, Cygwin & Linux), mais utiliser SEH garantit le code ne construira pas sur une autre plate-forme, à moins que vous ne décidiez de vous gêner avec le préprocesseur.
@valdo: MiniDumpwriDeDmp Code> doit charger d'autres DLL. Si vous avez rencontré une exception tout en maintenant la serrure du chargeur, vous feriez mieux de l'appeler à partir du processus. De plus, si vous avez une corruption de mémoire (une cause commune de bugs que vous voudriez avoir une décharge), vous devriez à nouveau appeler
miniduumpwridamep code> hors processus.
Si DosomOnner code> appelle Winapi
sendMessage () code> et c ++ exception est survenu dans son gestionnaire (c'est mon code aussi),
benneXc () code> n'est pas tiré. et le débogueur affiche un avertissement sur une exception non gérée. Pourquoi?
@ 23W: Parlez-vous d'une exception non conventionnelle (qui est un crash plutôt que d'avertissement), ou un message de débogueur d'exception de 1ère chance? Si ce dernier est le cas, alors c'est probablement parce que sendmessage code> a son propre gestionnaire de Seh, qui gère cette exception.
@Valdo, sur un message de débogueur d'exception de 1ère chance
SEH impose des restrictions sérieuses sur ce que le code à l'intérieur du bloc peut faire. Je n'ai pas utilisé Seh pendant un moment, mais la dernière fois que j'ai essayé, cela ne permettait pas d'obtenir des objets dans le cadre local qui avaient des destructeurs.
Un astuce qui est compilateur indépendant consiste à envelopper la déclaration de lancer dans une fonction. La fonction peut effectuer d'autres tâches avant de lancer l'exception, telles que l'enregistrement dans un fichier journal. Cela fait également un endroit pratique pour mettre un point d'arrêt. Si vous créez une macro pour appeler la fonction, vous pouvez incluez automatiquement le fichier __ __ code> et
__ ligne __ code> où le lancer est survenu. P>
Il est possible de concevoir vos exceptions pour inclure les noms de fichiers source et les numéros de ligne. Pour ce faire, vous devez créer une classe dérivée de std :: exception code> pour contenir les informations. Dans l'exemple ci-dessous, j'ai une bibliothèque d'exceptions pour mon application, y compris
my_exception code>. J'ai aussi un
traced_error code> une classe d'exception de modèle dérivée de mes exceptions de niveau d'application. L'exception
traced_error code> contient des informations sur le nom de fichier et le numéro de fichier, puis appelle la classe d'exception de niveau d'application '
what () code> méthode pour obtenir des informations d'erreur détaillées.
#include <cstdlib>
#include <string>
#include <stdexcept>
#include <iostream>
using namespace std;
template<class EX>
class traced_error : virtual public std::exception, virtual public EX
{
public:
traced_error(const std::string& file, int line, const EX& ex)
: EX(ex),
line_(line),
file_(file)
{
}
const char* what() const
{
std::stringstream ss;
static std::string msg;
ss << "File: " << file_ << " Line: " << line_ << " Error: " << EX::what();
msg = ss.str().c_str();
return msg.c_str();
}
int line_;
std::string file_;
};
template<class EX> traced_error<EX> make_traced_error(const std::string& file, int line, const EX& ex)
{
return traced_error<EX>(file, line, ex);
}
class my_exception : virtual public std::exception
{
public:
my_exception() {};
const char* what() const
{
return "my_exception's what";
}
};
#define throwx(EX) (throw make_traced_error(__FILE__,__LINE__,EX))
int main()
{
try
{
throwx(my_exception());
}
catch( const std::exception& ex )
{
cout << ex.what();
}
return 0;
}
Dupliqué possible de trace de pile d'affichage C ++ sur exception