Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1387 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Suivante
Auteur Sujet :

[C++] Debug assertion failed, quesako?

n°330898
BifaceMcLe​OD
The HighGlandeur
Posté le 12-03-2003 à 16:58:06  profilanswer
 

Reprise du message précédent :

sowhatin22 a écrit :


J'avoue que justement, je me suis toujours demandé à quoi servent réellement les exceptions... Ton explication m'interesse. Aurais-tu un(des) lien(s) sur un(des) exemple(s) concret(s)?


Pas de lien, désolé.
Comme je le disais, c'est un "goto sur erreur" masqué (comme le "while" et le "for" sont des gotos conditionnels).
En C, les fonctions qui traitent les erreurs ont souvent la structure suivante :

Code :
  1. int  err;
  2. ... // On alloue des ressources
  3. err = appel1(...);
  4. if (err) goto ERROR;
  5. err = appel2(...);
  6. if (err) goto ERROR;
  7. ...
  8. return; // fin normale de la fonction
  9. ERROR:
  10. // On désalloue les ressources.


C'est ce qu'on a trouvé de plus lisible pour centraliser la désallocation des ressources, et donc éviter la duplication de ce code. Mais tu remarqueras que cela utilise des gotos, ce qui n'est guère lisible, et rompt la structure de la fonction (les appels de fonction peuvent se trouver dans des boucles).
 
Avec un mécanisme d'exceptions, on a un code similaire, mais plus lisible :

Code :
  1. try {
  2.   ... // On alloue des ressources
  3.   appel1(...);
  4.   appel2(...);
  5.   ...
  6. }
  7. catch (Error e) {
  8.   // On désalloue les ressources.
  9. }


Autre avantage : non seulement la fonction peut récupérer sur erreur, mais l'appelant peut faire de même si la fonction ne souhaite pas traiter l'erreur.

mood
Publicité
Posté le 12-03-2003 à 16:58:06  profilanswer
 

n°330900
chrisbk
-
Posté le 12-03-2003 à 16:59:22  profilanswer
 

au fait, comment les exceptions sont implantes dans un langage tel que le C++ ? Lorsqu'un throw est appele, comment l'exception remonte t'elle jusqu'au block catch() correspondant ?  

n°330910
nraynaud
lol
Posté le 12-03-2003 à 17:04:39  profilanswer
 

BifaceMcLeOD a écrit :


Avec un mécanisme d'exceptions, on a un code similaire, mais plus lisible :

Code :
  1. try {
  2.   ... // On alloue des ressources
  3.   appel1(...);
  4.   appel2(...);
  5.   ...
  6. }
  7. catch (Error e) {
  8.   // On désalloue les ressources.
  9. }


Autre avantage : non seulement la fonction peut récupérer sur erreur, mais l'appelant peut faire de même si la fonction ne souhaite pas traiter l'erreur.


 
Juste un détail pour les gens qui lisent : souvent, c'est l'ouverture de la ressource qui risque de se planter, c'est pour ça qu'on met des hiérachies de try/catch pour ne fermer que ce qui a été réllement ouvert, et pas tout en bloc.
 
 
Autre chose : la dernière fois que j'ai (vraiment) touché à du C, j'ai carrément écrit des fonctions imbriqués pour pouvoir traiter proprement les échecs d'ouvertures de ressources parceque c'était vraiment trop catastrophique (y'avait plusieurs trucs à ouvrir, traiter et fermer tout).

n°330916
BifaceMcLe​OD
The HighGlandeur
Posté le 12-03-2003 à 17:09:41  profilanswer
 

Le principe des exceptions, quel que soit le langage, c'est, lorsqu'une exception est levée :  

  • Etape 1 : le système regarde si l'instruction qui a déclenché l'exception se trouve dans un bloc qui possède un traite-exceptions. Si oui, étape 2, sinon, étape 3.
  • Etape 2 : Deux cas : si parmi les types d'exceptions que traite le bloc traite-exceptions, il y a celui de l'exception levée, on exécute ce code-là et l'erreur disparait, sinon étape 3.
  • Etape 3 : S'il n'y a pas d'appelant, étape 4 ; sinon, on remonte à cet appelant et on considère l'appel comme l'instruction qui a déclenché l'exception. Etape 1.
  • Etape 4 : le programme se termine, avec l'erreur "Exception non traitée" (un peu comme une assertion).


Généralement, le langage offre un mécanisme pour fabriquer une exception dans le code normal, et pour relancer une exception qu'on est en train de traiter ("raise", "throw" selon les langages).

n°330918
BifaceMcLe​OD
The HighGlandeur
Posté le 12-03-2003 à 17:11:52  profilanswer
 

nraynaud a écrit :


 
Juste un détail pour les gens qui lisent : souvent, c'est l'ouverture de la ressource qui risque de se planter, c'est pour ça qu'on met des hiérachies de try/catch pour ne fermer que ce qui a été réllement ouvert, et pas tout en bloc.


Une autre solution, c'est d'initialiser tous ses objets/pointeurs/whatever à NULL avant d'allouer les ressources. Dans ce cas, un seul catch suffit : seules les ressources non-NULLes sont à désallouer.

n°330920
nraynaud
lol
Posté le 12-03-2003 à 17:13:01  profilanswer
 

chrisbk a écrit :

au fait, comment les exceptions sont implantes dans un langage tel que le C++ ? Lorsqu'un throw est appele, comment l'exception remonte t'elle jusqu'au block catch() correspondant ?  
 


D'un point de vue conceptuel :
lorsques tu entres dans un bloc try/catch, tu marques la pile.
 
Lorsque l'exception est levée, tu arrêtes le programme, tu dépile frame par frame jusqu'à trouver une marque. tu regardes la tronche du catch, s'il peut catcher ton exception, tu lui file, tu mets le pointeur d'instruction au début du catch et tu relances le programme. Sinon tu continue à remonter.
 
Normalenent, le main() est lancé dans un bloc try/catch qui peut tout catcher avec un handler par défaut (je spécule mais c'est l'idée des exceptions).

n°330927
gatorette
Posté le 12-03-2003 à 17:15:44  profilanswer
 

Je suis tout à fait d'accord avec le bien fondé des exceptions mais pour moi les assertions ont aussi leur place.
En effet, une exception traîtent des cas exceptionnels mais relativement normaux (une erreur quelconque qui n'est pas un bug).
Par contre, les assertions gèrent les cas qui ne peuvent (et ne doivent) pas arriver dans le programme. Elles permettent de révéler des bugs dans le code (et non pas des erreurs "normales" ).
Un programme bien écrit ne doit jamais "asserter" alors qu'il peut bien évidemment lancer des exceptions.


---------------
each day I don't die is cheating
n°330933
Taz
bisounours-codeur
Posté le 12-03-2003 à 17:17:31  profilanswer
 

BifaceMcLeOD a écrit :


Une autre solution, c'est d'initialiser tous ses objets/pointeurs/whatever à NULL avant d'allouer les ressources. Dans ce cas, un seul catch suffit : seules les ressources non-NULLes sont à désallouer.

sauf quand t'as par exemple des descripteur de fichiers, qu'une erreur d'E/S s'est produit, vas t'en savoir lequel est fermé, lequel l'es po. et si les seuls problèmes qu'on aa avaient pour simple solution des free, ça serait du gateau. mais la plus par du tmeps on a beaucoup plus de choses à faire, des choses beaucoup plus compliquées (le tout étant de savoir ou le problème est arrivé et comment le traiter sans faire de nouvelles erreurs.

n°330934
nraynaud
lol
Posté le 12-03-2003 à 17:18:10  profilanswer
 

BifaceMcLeOD a écrit :


Une autre solution, c'est d'initialiser tous ses objets/pointeurs/whatever à NULL avant d'allouer les ressources. Dans ce cas, un seul catch suffit : seules les ressources non-NULLes sont à désallouer.


 
Argggg je peux pas, désolé mais j'ai trop bossé avec des langages fonctionnels. Je peux plus supporter les nullPointerException etc.  
 
Pour moi on en reviens à la valeur spéciale qui fait passer un message d'erreur (au C quoi).

n°330935
Taz
bisounours-codeur
Posté le 12-03-2003 à 17:19:08  profilanswer
 

nraynaud a écrit :


Pour moi on en reviens à la valeur spéciale qui fait passer un message d'erreur (au C quoi).

qui est effectivemnt un code d'erreur

mood
Publicité
Posté le 12-03-2003 à 17:19:08  profilanswer
 

n°330952
nraynaud
lol
Posté le 12-03-2003 à 17:25:18  profilanswer
 

++Taz a écrit :

qui est effectivemnt un code d'erreur


 
Et qui va te pêter à la gueule un jour où l'autre.

n°330978
BifaceMcLe​OD
The HighGlandeur
Posté le 12-03-2003 à 17:50:44  profilanswer
 

++Taz a écrit :

sauf quand t'as par exemple des descripteur de fichiers, qu'une erreur d'E/S s'est produit, vas t'en savoir lequel est fermé, lequel l'es po. et si les seuls problèmes qu'on aa avaient pour simple solution des free, ça serait du gateau. mais la plus par du tmeps on a beaucoup plus de choses à faire, des choses beaucoup plus compliquées (le tout étant de savoir ou le problème est arrivé et comment le traiter sans faire de nouvelles erreurs.


Si : free() + Réinitialisation à NULL.
Mais par contre, je t'accorde que le choix de savoir quoi faire sans déclencher de nouvelles exceptions peut être de loin beaucoup plus délicat.

n°330986
Taz
bisounours-codeur
Posté le 12-03-2003 à 17:55:48  profilanswer
 

BifaceMcLeOD a écrit :


Si : free() + Réinitialisation à NULL.
Mais par contre, je t'accorde que le choix de savoir quoi faire sans déclencher de nouvelles exceptions peut être de loin beaucoup plus délicat.
 

re: y a pas que des problèmes de malloc dans la vie

n°330992
BifaceMcLe​OD
The HighGlandeur
Posté le 12-03-2003 à 17:57:56  profilanswer
 

nraynaud a écrit :


 
Argggg je peux pas, désolé mais j'ai trop bossé avec des langages fonctionnels. Je peux plus supporter les nullPointerException etc.  
 
Pour moi on en reviens à la valeur spéciale qui fait passer un message d'erreur (au C quoi).


Les NullPointerException's ont au moins un avantage : le programme ne plante jamais 3 heures plus tard. C'est donc un mal bien moindre que l'erreur qui a motivé Alload pour créer ce topic : une erreur dont on ne voit les effets -- catastrophiques -- que des dizaines voire des centaines ou milliers d'instructions plus tard.
 
Et comme l'a dit Taz, les exceptions doivent rester exceptionnelles. Une référence à NULL, si comme si tu avais un booléen accompagnant la référence pour dire "cette référence est valide/pas valide". Et il ne faut pas écrire :

Code :
  1. try {
  2.   Libère(maRessource);
  3. }
  4. catch (NullPointerException e) {
  5.   // Ah ben on ignore, la ressource était déjà libérée !
  6. }


mais :

Code :
  1. if (maRessource != null) {
  2.   Libère(maRessource);
  3.   maRessource = null;
  4. }

n°330996
BifaceMcLe​OD
The HighGlandeur
Posté le 12-03-2003 à 18:01:05  profilanswer
 

++Taz a écrit :

re: y a pas que des problèmes de malloc dans la vie


L'expérience montre 70 % des bugs dans les programmes de l'industrie sont des bugs mémoires. Donc des bugs de malloc.
 
Si tu arrives à les éliminer tous, déjà, tu as fait un sacré ménage, et ton programme est d'une qualité clairement supérieure.
 
Maintenant, bien sûr que tous les bugs ne sont pas des bugs mémoire. Mais les bugs non-mémoire ont un risque infiniment plus faible de déstabiliser l'application au point de la tuer. Autrement dit, la récupération sur erreur est beaucoup plus facile et moins risquée.
 
Mais, au risque de me répéter, tant que la majorité des programmes seront écrits en C ou en C++, le problème principal et réddhibitoire du logiciel sera les bugs mémoire.


Message édité par BifaceMcLeOD le 12-03-2003 à 18:02:27
n°331128
Taz
bisounours-codeur
Posté le 12-03-2003 à 19:56:18  profilanswer
 

oui. par ce que les destructeur sont appelés.

n°331892
BifaceMcLe​OD
The HighGlandeur
Posté le 13-03-2003 à 10:35:21  profilanswer
 

briseparpaing a écrit :


 
Donc, tu penses que la gestion des problèmes d'allocation/désallocation mémoire est à traiter en priorité via le mécanisme d'exceptions ?
Les classes standards (genre vector) comportent déjà un mécanisme d'exceptions.  
Si on combine les deux (mémoires+conteneurs standards), on devrait arriver à un programme déjà bien robuste, non ?  


Ce n'est pas ce que je voulais dire. Je ne lie aucunement exceptions et problèmes mémoire. L'un est un mécanisme à la fois puissant, souple et fin pour la récupéation sur erreur -- qu'il s'agisse d'une erreur mémoire, d'une division par zéro ou d'un serveur distant qui est tombé ; l'autre est le problème numéro 1 des logiciels dans l'industrie aujourd'hui.
 
Maintenant, les conteneurs standard sont encore un autre outil, qui permet une gestion mémoire à la fois efficace et cachant/encapsulant la principale source d'erreurs mémoire : l'usage explicite des pointeurs. Donc, oui, ta conclusion est juste : un programme qui utilise les exceptions et les conteneurs, et qui utilise aussi peu que possible les pointeurs, est nettement plus facile à rendre robuste qu'un programme C classique.
 
edit> Je ne lie pas exceptions et bugs mémoire, par contre, les conteneurs sont une réponse tout à fait appropriée aux bugs mémoire inhérents à la manipulation explicite de pointeurs.


Message édité par BifaceMcLeOD le 13-03-2003 à 10:36:49
n°332071
nraynaud
lol
Posté le 13-03-2003 à 13:30:34  profilanswer
 

BifaceMcLeOD a écrit :


un programme qui utilise les exceptions et les conteneurs, et qui utilise aussi peu que possible les pointeurs, est nettement plus facile à rendre robuste qu'un programme C classique.


 
Et éviter d'utiliser un langage où il y a des pointeurs ? Ça aurait l'avantage que même les parties que tu n'a pas écrites te garantissent qu'il n'y a pas de pointeur qui se balade.

n°333026
BifaceMcLe​OD
The HighGlandeur
Posté le 14-03-2003 à 10:31:13  profilanswer
 

Les pointeurs existent en Pascal comme en Ada, c'est donc qu'il existent des cas où on ne sait pas faire sans. D'ailleurs, c'est un type de données algorithmique.
 
Mais il y a un monde entre n'utiliser que des pointeurs au sens algorithmique du terme et mettre des pointeurs à toutes les sauces.

n°333340
nraynaud
lol
Posté le 14-03-2003 à 13:11:17  profilanswer
 

BifaceMcLeOD a écrit :

Les pointeurs existent en Pascal comme en Ada, c'est donc qu'il existent des cas où on ne sait pas faire sans. D'ailleurs, c'est un type de données algorithmique.
 
Mais il y a un monde entre n'utiliser que des pointeurs au sens algorithmique du terme et mettre des pointeurs à toutes les sauces.


 
Je parlais bien entendu de pointeurs manipulables au sens du C, dans le cas général d'un identifieur d'objet, le terme général est référence, qui ne suppose pas que c'est une adresse mémoire ni la moindre relation d'ordre entre les objet (puisque pendant lontemps ça a été les index 16bits de l'objet dans la table d'objet).
 
Mais si tu veux jouer sur les mots, tu peux.
 
 
edit : dailleur en Java, Smalltalk, LISP etc. on ne peut manipuler (sémantiquement) que des références et tout le monde est content.


Message édité par nraynaud le 14-03-2003 à 13:17:32
n°337190
BifaceMcLe​OD
The HighGlandeur
Posté le 19-03-2003 à 13:24:59  profilanswer
 

nraynaud a écrit :


 
Je parlais bien entendu de pointeurs manipulables au sens du C, dans le cas général d'un identifieur d'objet, le terme général est référence, qui ne suppose pas que c'est une adresse mémoire ni la moindre relation d'ordre entre les objet (puisque pendant lontemps ça a été les index 16bits de l'objet dans la table d'objet).
 
Mais si tu veux jouer sur les mots, tu peux.
 
 
edit : d'ailleurs en Java, Smalltalk, LISP etc. on ne peut manipuler (sémantiquement) que des références et tout le monde est content.


Moi, il me semblait précisément qu'en C, la définition même d'une variable pointeur, c'était, selon Kernighan et Ritchie en personne(s?) "une variable qui contient l'adresse d'une autre variable". Adresse mémoire, sous-entendu. Ce qui signifie que l'instruction "int* p = (int*) 0x2F652C;", qui fait directement pointer quelquepart en mémoire, est parfaitement valide.
 
Alors qu'en Java, en SmallTalk et en Lisp, il s'agit bien de références sur d'autres objets, je suis d'accord.

n°338151
Musaran
Cerveaulté
Posté le 20-03-2003 à 07:14:39  profilanswer
 

BifaceMcLeOD a écrit :

Mais je le répète : le mécanisme d'exceptions n'est ni plus ni moins qu'un goto sur erreur.


Oui, mais c'est beaucoup plus sophistiqué quand même:
+Destination (code de gestion) déterminée à l'exécution.
+Rebrousse chemin, simplifiant le problème de sortie.
+Destruction proprement des objets trouvés en chemin, donc libération des ressources.
+Ne parasite pas le source avec de codes de retour, valeurs réservées et tests.
 
 

nraynaud a écrit :

Et éviter d'utiliser un langage où il y a des pointeurs ?

Le meilleur moyen de ne pas se couper, c'est de ne pas utiliser de couteau.
C'est aussi se priver d'un outil puissant...


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°339454
BifaceMcLe​OD
The HighGlandeur
Posté le 21-03-2003 à 10:22:40  profilanswer
 

Musaran a écrit :


Oui, mais c'est beaucoup plus sophistiqué quand même:
+Destination (code de gestion) déterminée à l'exécution.
+Rebrousse chemin, simplifiant le problème de sortie.
+Destruction proprement des objets trouvés en chemin, donc libération des ressources.
+Ne parasite pas le source avec de codes de retour, valeurs réservées et tests.


Ah, mais je n'ai pas dit le contraire.  :)  
De même que le "while" et le "for", bien que fondamentalement équivalents à un goto conditionnel, sont aussi bien plus sophistiqués (tu peux leur appliquer au moins les 3 premiers avantages de ta liste). Mais remémore-toi les débats qu'il y a eu à l'époque sur le goto (notamment le fameux article de Dijkstra "Goto considered harmful" et toutes les réponses qu'il a pu avoir, y compris ""Goto considered harmful" considered harmful" ).

n°339620
nraynaud
lol
Posté le 21-03-2003 à 14:03:07  profilanswer
 

[citation=338151,2][nom]
Le meilleur moyen de ne pas se couper, c'est de ne pas utiliser de couteau.
C'est aussi se priver d'un outil puissant...
[/citation]
 
Le problème est : un couteau dont on a que la lame est-il vraiment l'outil adapté pour changer la couche d'un bébé ?¿? Utiliser n'importe quel outil pour faire n'importe quoi sous prétexte que qu'il y a des milieu ou il a été un jour le mieux adapté me parraît un peu douteux.
 
Je me demande d'ailleur pourquoi l'assembleur n'a plus la cote car il offre une liberté inégalée avec le programme.


Message édité par nraynaud le 21-03-2003 à 14:04:55
n°339637
BifaceMcLe​OD
The HighGlandeur
Posté le 21-03-2003 à 14:24:24  profilanswer
 

nraynaud a écrit :


Je me demande d'ailleurs pourquoi l'assembleur n'a plus la cote car il offre une liberté inégalée avec le programme.


C'est ce que j'ai failli répondre ce matin à un autre forumeur sur un autre topic... :D  :jap:

n°340303
Musaran
Cerveaulté
Posté le 22-03-2003 à 08:09:41  profilanswer
 

nraynaud a écrit :

Le problème est : un couteau dont on a que la lame est-il vraiment l'outil adapté pour changer la couche d'un bébé ?¿? Utiliser n'importe quel outil pour faire n'importe quoi sous prétexte que qu'il y a des milieu ou il a été un jour le mieux adapté me parraît un peu douteux.

Ah mais tout à fait.
Quand on en a marre de se couper, on comprend d'autant mieux l'utilité du manche, et l'intérêt qu'il soit ergonomique.
C'est encore mieux avec une trancheuse qui est calibrée et protégée.
 
La lame de rasoir n'en reste pas moins nécessaire parfois.
 
 
Et puis d'abord en C on se coupe pas, on se tire une balle dans le pied.
 
Waow les analogies foireuses... :sweat:


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Suivante

Aller à :
Ajouter une réponse
 

Sujets relatifs
PHP Mail() failed to connectTomcat & Struts 1.1 ... et les millions de ligne de debug !!
ident failed for user machin?? d'où ça vient (Postgres inside)[résolu]éditeur qui debug pas à pas à la visual C++
[easy debug] MySQL et INSERT INTOIntelliJ Idea 3.0 - Debug de JSP
[VISUAL C++]Difference entre Release/Debug[VISUAL C++] difference d execution entre mode debug et release
MySQL : activer le mode "debug" sous Linux ?PHPBB : 'Failed sending mail' /Free\ (soluce inside:codes et modifs)
Plus de sujets relatifs à : [C++] Debug assertion failed, quesako?


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR