J'ai une API qui présente des exceptions à l'intérieur des exceptions pour les rapports d'erreur. La structure de base est qu'elle a un objet d'exception racine qui hérite de Étant donné qu'une exception projetée dans une bibliothèque ou un fil et l'attraper dans une autre peut conduire à un comportement indéfini (au moins qt se plaint de cela et le désactive dans de nombreux contextes). J'aimerais envelopper les appels de bibliothèque dans des fonctions qui renvoient un code d'état et, si une exception s'est produite, une copie de l'objet d'exception. P>
Quelle est la meilleure façon de Store forte> une exception (avec son comportement polymorphique) pour une utilisation ultérieure? Je crois que l'API future C ++ 0x utilise quelque chose comme ça. Alors quelle est la meilleure approche? P>
Le meilleur que je peux penser est d'avoir un Toutes les pensées? P>
edit fort>: on dirait que Boost a un Mise en œuvre de la copie d'exception . Je vais garder la question ouverte pour tout EDIT STRY>: Pour adresser les préoccupations de J_Random_Hacker sur la cause première de l'exception étant une erreur de mémoire hors mémoire. Pour cette bibliothèque particulière et cette série d'exceptions, ce n'est pas le cas. Toutes les exceptions dérivées de l'objet d'exception racine représentent différents types d'erreurs d'analyse causées par une entrée d'utilisateur non valide. Les exceptions relatives à la mémoire provoqueront simplement un std :: exception code>, alors il lancera une sous-classe de celle-ci. P>
clone () code> méthode dans chaque classe d'exception qui retournera un pointeur à une exception du même type. Mais ce n'est pas très générique et ne traite pas du tout des exceptions standard. P>
boost :: copy_exception code> réponses. P>
std :: Bad_alloc Code> pour être jeté qui est adressé séparément. P>
5 Réponses :
Vous avez ce que vous seriez ce que je pense, c'est de votre mieux, seulement répondre. Vous ne pouvez pas conserver une référence à l'exception originale car elle va quitter la portée. Vous devez simplement en faire une copie et la seule façon générique de faire est avec une fonction prototype comme Clone (). P>
désolé. p>
Mais méfiez-vous que la cause première de l'exception peut être une condition hors mémoire, auquel cas clone () code> échouera s'il tente d'appeler
nouveau code>. Cela peut être venu, par ex. En surcharge
Opérateur Nouveau () Code> Pour chaque type d'exception à allouer à partir d'un tampon statique, mais ce n'est pas nécessairement assez non plus.
@J_Random_hacker: Eh bien, puisque nous obtenons Pedantic, ce que vous appelez hors de mémoire, c'est mieux appelé Bad-Alloc et qu'il ne doit pas nécessairement être réel de mémoire. Une autre raison de Bad-Alloc demande trop de mémoire et, dans ce cas, les petites allocations ultérieures vont réussir
@sbk: Est-ce vraiment pédant à considérer la possibilité de manquer de mémoire?
La réponse facile ici est de souligner qu'avec Bad_alloc, vous avez), et b) Obtenir une exception particulière que vous ne serez pas capable de clone car ce ne sera pas le vôtre.
Vous êtes autorisé à jeter quoi que ce soit, y compris les pointeurs. Vous pouvez toujours faire quelque chose comme ceci: puis dans le gestionnaire d'exception stocker le pointeur capturé, qui sera entièrement polymorphe (ci-dessous en supposant que Il suffit de faire attention aux fuites de mémoire lorsque vous le faites de cette façon, c'est pourquoi La valeur et la référence à la référence sont normalement utilisées. P> plus sur Catch-by-Pointer: http://www.parashift.com/c++-faq-lite/Exception.html#faq-17.8 P> p> myException code> dérive de < code> std :: exception code>): p>
Le problème avec cette solution, car je vois que vous vusez peut-être une exception en raison de quelque chose qui a pour conséquence saine une condition hors mémoire, auquel cas nouveau code> échouera.
Cela a été mentionné dans le lien, mais vous pourriez dans la théorie de travailler autour de cela en ayant une exception préalablement allouée ou statique en mémoire de mémoire que vous lancez dans ce cas. Mais vous auriez alors besoin de vous assurer que vous ne supprimez pas cela comme vous le feriez vos autres exceptions. C'est difficile mais vous devez faire attention à beaucoup de pièges comme celui-ci.
Ne pouvions-nous pas vérifier si l'exception indique une condition de mémoire hors mémoire et simplement définir un int / booléen pour l'indiquer?
+1: Pour mon usage particulier, cela n'est pas une mauvaise idée. semblable à l'approche clone mais faisant au point de lancer.
La raison pour laquelle attraper une exception projetée dans une bibliothèque et l'attraper dans une autre peut conduire à un comportement indéfini est que ces bibliothèques pourraient être liées à différentes bibliothèques d'exécution. Si vous retournerez une exception d'une fonction au lieu de le jeter, vous n'évitez pas ce problème. P>
Je crois que vous êtes correct, je pense que la question Qt a avec elle est davantage de passer entre les threads (j'ai ajouté cette subtilité à ma question aussi).
My Utility Library possède une classe Il s'agit d'une simplification, mais c'est le cadre de base. Mon code actuel désactive la copie et a plutôt déplacé la sémantique. Si nécessaire, vous pouvez ajouter une méthode virtuelle Quand cela a été conçu, c'était Non destiné à stocker des exceptions attrapées ... Une fois une exception, elle a été lancée, elle s'est propagée comme normale, les conditions hors de mémoire n'étaient pas envisagées. Cependant, j'imagine que vous pouvez ajouter une instance de i Haven 't en fait testé ce deuxième bit du tout ... Je serais peut-être manquant quelque chose d'évident évident qui l'empêchera de travailler. P> p> AnyException code> de la même manière que
boost :: n'importe quel code> sans le support de casting. Au lieu de cela, il possède un membre
() code> qui jette l'objet d'origine stocké.
clone code> à la
exceptebase code> assez facilement ... car
exception code> connaît le type d'origine de l'objet, il peut transmettre la demande sur le constructeur de copie réelle et vous avez immédiatement un support pour tous les types copiables, pas seulement avec leurs propres
clone code> méthode. p>
std :: bad_alloc code> à l'objet et stockez-la directement dans ces situations. P>
AS de C ++ 11, cela peut être fait avec STD :: Exception_Ptr.
(J'utilise cela dans une classe qui fait un STD :: filetage interruptible à condition que l'implémentation de thread sous-jacent est un thread de POSIX. Pour gérer des exceptions pouvant être lancées dans le code de l'utilisateur - qui provoque des problèmes si elles sont lancées dans une certaine section critique de ma mise en œuvre - je stocke l'exception en utilisant STD :: Exceptionnel_ptr, puis la jetez plus tard une fois la section critique terminée.) P>
Pour stocker l'exception, vous l'attrapez et stockez-le dans le PTR Variable. P>
try { if (eptr) { std::rethrow_exception(eptr); } } catch (const std::exception& e) { ... examine e ... } catch (...) { ... handle any non-standard exceptions ... }