Les Exceptions C++ - jette le c-string comme une exception mauvais?
Je suis en train de travailler sur un petit programme en c++ et de l'apprentissage des exceptions. Est le code suivant "mauvais", et si oui, que puis-je faire pour l'améliorer?
try {
//code
if (some error) {
throw "Description of error.";
}
}
catch (char* errorMessage) {
cerr << errorMessage << endl << "Fatal error";
}
Il n'y a rien de mal à jeter un char
tableau comme une exception?
EDIT:
Cela serait-il une meilleure façon d'aller?
const char errorMessage[] = "Description of error";
try {
//code
if (some error) {
throw errorMessage;
}
}
catch (char* errorMessage) {
cerr << errorMessage << endl << "Fatal error";
}
- Une recherche titre pourrait être "le langage C++ est-il mauvais pour lancer une chaîne de caractères comme une exception?".
- Ce n'est pas un std::string, mais un c-type de chaîne
- Le point est que le titre n'est pas consultable, et je pense qu'il serait bon de le changer. Mais à l'adresse de votre point de vue, je pense que la "chaîne" est communément utilisé pour désigner un std::string ou l'une des nombreuses variantes de char*, et en regardant la accepté de répondre, il serait encore applicable à la question posée.
Vous devez vous connecter pour publier un commentaire.
Il est beaucoup mieux pour lancer un standard de l'objet exception. En général, la meilleure pratique est de jeter quelque chose dérivé de
std::exception
de sorte que si, dans certaines situation, il est la cause de votre programme de résilier, de la mise en œuvre a une meilleure chance de l'impression d'un diagnostic utile.Parce qu'il n'est pas difficile à faire, je ne recommanderais jamais à jeter un raw un littéral de chaîne.
std::exception
dont surchargéwhat()
retourné un pointeur vers une chaîne littérale. De l'espace pour un objet d'exception (même si seulement un pointeur) doit toujours être de répartir et de l'objet de l'exception initialisé à chaque fois qu'une exception est levée.std::exception
des objets dérivés de toute façon, re "de l'Espace pour un objet d'exception (même si seulement un pointeur) doit toujours être de répartir et de l'objet de l'exception initialisé à chaque fois qu'une exception est levée." - il est possible que le tas soit épuisé (et doncstd::string
être incapable denew
), sans la pile étant épuisé (ce qui est tout ce qui est nécessaire pour un pointeur)....throw
n'échoue jamais. Si c'est un pointeur ou un objet qui peut être initialisé sans allouer plus de mémoire dans la mémoire maintenant ne fait aucune différence.run_time
erreur de la chaîne se trouve sur le tas, et si je le fais à l'aide d'une chaîne brute, il se réfère à la chaîne de caractères qui est déjà sur la pile?std::exception
ne contient pas une chaîne de caractères (ou ne devrait pas l'---de ce qu'il contient est, bien sûr, dépendant de l'implémentation). Pour les exceptions, ce qui peut être levée lorsque les ressources sont limitées, vous pouvez dériver directement à partir destd::exception
, et remplacerwhat
pour retourner une chaîne constante. (C'est ce qui est ce que j'attends destd::bad_alloc
, par exemple.)std::runtime_error
magasins de la chaîne de qui il est construit avec. Généralement (mais pas nécessairement), cela implique la mémoire allouée dynamiquement. Un littéral de chaîne statique de la durée de stockage. Si vous jetez quelque chose qui pointait vers un objet automatique de la durée de stockage (par exemple, unchar
tableau "sur la pile") et que cet objet n'était pas dans le champ d'application dans le gestionnaire d'exception alors vous avez un sérieux potentiel d'erreur.max(sizeof
jeté des objets)
, mais qui ne peuvent toujours pas en mesure d'évaluer les besoins des pointeurs à partir de ces objets, qui peuvent au moment de l'exécution de la poignée d'un segment, alors il est idéal de ne pas en avoir.std::runtime_error
les implémentations de tenir unestd::string
....std::exception
. Vous pouvez dérivé destd::exception
pour créer des exceptions qui ne nécessitent pas de façon dynamique les ressources allouées, dans le cas particulier où les ressources sont limitées.std::runtime_error
. À mon humble avis, typique de non-incorporé des systèmes de serveur peuvent rarement se remettre de la mémoire de l'épuisement, et en supposant qu'ils sont en 64 bits, avec une abondante swap ils vont ralentir massivement à l'avance que la mémoire virtuelle contraintes kick, donc il n'y a que peu de valeur en étant prudent.const char*
avec uncatch( char* )
.exception(const char * const &)
qui rend malloc et des copies de la chaîne. Même si ils ne l'ont pas fait, ils auraient à faire à cette répartition dans chaque classe descendante.std::exception
, et n'a qu'un défaut constructeur, et DM propose un choix de constructeurs: un seul de qui alloue de la mémoire. Il est essentiel que les classes dérivées commestd::bad_alloc
peut être construit sans l'allocation des ressources. C'est seulement à la plus complexe de types d'exceptions dans<stdexcept>
qui nécessitent l'allocation dynamique.Jeter un littéral de chaîne est généralement une mauvaise idée parce que, comme le code évolue, les programmeurs peuvent avoir besoin d'enrichir le message d'erreur avec un peu plus de renseignements, par exemple, la valeur d'une variable, ou le nombre de ligne à partir de laquelle l'exception est levée.
Donnée inconnue code client que de prendre
const char*
, le programmeur a encouragé l'utilisation d'un mécanisme dynamique pour concaténer information souhaitée:std::string
et+
std::ostringstream
strcat
et/ousprintf()
Le moyen le plus évident de l'utilisation de ces ne fonctionnent pas ou ne fonctionnent pas bien:
Même si le programmeur ne sait pas faire un de ces, ils auront toujours un bon moment de trouver tous les codes du client, qui doit commencer à accepter un riche type de valeur, surtout si d'autres
throw
/catch
utilisation deconst char*
persiste.Donc, à l'aide d'une classe qui intègre un flexible
std::string
description en valeur est très important pour l'écriture de code maintenable.Aucun problème à lancer un
char
tableau. Juste que vous devriez recevoir comme1er
const
est d'ajouter de la capacité de recevoir toutchar
tableauchar*
const char*
char[]
const char[]
2e
const
est à préciser queerrorMessage
n'est pas prévu de changement au sein decatch
blocconst
est de l'intention,errorMessage
n'est pas censé changer.const
sur les paramètres de la fonction est de préserver la mise en œuvre des libertés sans l'introduction de la recompilation des dépendances (physique des dépendances dans Lakosian termes)... qui ne s'applique pas ici.Il y a la question générale de ne pas être en mesure de filtrer facilement vos exceptions et d'agir sur eux en fonction de leur type. Cependant, je ne sais pas si il y a un C++ de raison particulière de ne pas le faire
std::exception (ou au moins, std::runtime_error) contient une chaîne de caractères, qui peuvent être accessibles par le biais de la ce() la méthode. La meilleure chose que vous pouvez faire est de l'utiliser, car c'est la norme, et d'autre code peut attendre d'elle, et puisqu'il est votre but de toute façon.
Mieux coller à la norme dans ce cas.
Si votre idée de lancer une chaîne de caractères comme une erreur a été pour la commodité de montrer l'erreur à l'utilisateur, de considérer que ce serait faire de la localisation de votre application plus difficile (peut ou ne peut pas être un souci pour vous mais).
Également si une autre partie de l'application a besoin de comprendre ce que l'erreur est de sorte qu'il puisse y réagir (par exemple si c'est un décalage d'erreur, essayez de vous reconnecter automatiquement, mais si c'est une erreur de mot de passe, juste afficher de message d'erreur à l'utilisateur), il est préférable d'avoir une sorte de code d'erreur disponible à l'exception catcher.
Dans notre application, notre exceptions sont dérivées à partir de std::exception. Ils contiennent un type de l'erreur (enum), un debug message d'erreur (y compris le fichier/numéro de ligne), et localisée de la chaîne d'erreur.
Je pense que c'est beaucoup plus simple. :).