Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

gestionnaire d'erreurs rudimentaire

23 réponses
Avatar
nico
Salut,

Dans mes programmes, je suis toujours embété par la gestion des
désallocation d'objets lorsque survient une erreur quelconque...


par exemple, lors de la construction d'un objet important pour le
programme, il y a échec, je dois détruire tous les objets créés
auparavant afin de quitter proprement.. celà demande toujours des tests
ennuyeux, et de plus, la liste de ces objets à détruire n'est jamais la
même suivant l'endroit du programme où l'erreur survient.


J'ai donc dans l'idée de programmer un petit gestionnaire d'erreur, je
pensais à un objet qui contiendrait la liste des objets crées
(pointeurs) ainsi qu'un pointeur vers leur destructeur respecif et un
message char* approprié (tel que le nom etc...)

ainsi lors d'une erreur, il serait "facile" de détruire un à un les
objets alloués en affichant ça à l'utilisateur... :

objet 1... détruit
objet 2... détruit
objet 3... détruit
...
objet n... détruit

Cependant je pense à une chose délicate, afin d'etre le plus général
possible mon gestionnaire ne doit pas accumuler une liste d'objets sans
ordre... en effet il se peut que certains objets soient dépendant
d'autres, et que leur destructeur requiert qu'un des autres objets soit
encore en vie... il faudrait donc une sorte d'arborescence d'objets à
tuer...


Quelqu'un à -t-il déjà fait quelque chose de similaire ? avez-vous
une/des bonne(s) idée(s) à me proposer ?

merci
bon surf
a+


--
Nicolas Aunai
http:\\nicolas.auanai.free.fr

10 réponses

1 2 3
Avatar
Jean-Marc
"nico" a écrit dans le message de
news:42bd14aa$0$17123$
Salut,

Dans mes programmes, je suis toujours embété par la gestion des
désallocation d'objets lorsque survient une erreur quelconque...


par exemple, lors de la construction d'un objet important pour le
programme, il y a échec, je dois détruire tous les objets créés
auparavant afin de quitter proprement.. celà demande toujours des tests
ennuyeux, et de plus, la liste de ces objets à détruire n'est jamais la
même suivant l'endroit du programme où l'erreur survient.


J'ai donc dans l'idée de programmer un petit gestionnaire d'erreur, je
pensais à un objet qui contiendrait la liste des objets crées
(pointeurs) ainsi qu'un pointeur vers leur destructeur respecif et un
message char* approprié (tel que le nom etc...)

ainsi lors d'une erreur, il serait "facile" de détruire un à un les
objets alloués en affichant ça à l'utilisateur... :

objet 1... détruit
objet 2... détruit
objet 3... détruit
...
objet n... détruit

Cependant je pense à une chose délicate, afin d'etre le plus général
possible mon gestionnaire ne doit pas accumuler une liste d'objets sans
ordre... en effet il se peut que certains objets soient dépendant
d'autres, et que leur destructeur requiert qu'un des autres objets soit
encore en vie... il faudrait donc une sorte d'arborescence d'objets à
tuer...


Quelqu'un à -t-il déjà fait quelque chose de similaire ? avez-vous
une/des bonne(s) idée(s) à me proposer ?


Hello,

Quand tu parles de quitter proprement, tu parles de revenir à un point
donné de ton progrmmame, ou bien de quitter réellement l'application?

Dans le dernier cas, le problème ne se pose pas vraiment, si ce n'est
pour des raisons esthétiques: C'est le système d'exploitation qui va de
toute façon libérer tout ce qui a été alloué, en tout cas c'est comme
cela que ça fonctionne sur les OS que je connais.

Ainsi, il n'y a pas de fuite mémoire dans le programme suivant:

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
char *p;
p = malloc(1000);
return EXIT_SUCCESS;
}

En embarqué, je ne sais pas si la mémoire allouée par malloc() est
aussi libérée à la fin de l'exécution du programme, je suppose que
c'est le cas également. Me trompe je ?

--
Jean-marc
"There are only 10 kind of people
those who understand binary and those who don't."

Avatar
Emmanuel Delahaye
nico wrote on 25/06/05 :
Salut,

Dans mes programmes, je suis toujours embété par la gestion des désallocation
d'objets lorsque survient une erreur quelconque...

par exemple, lors de la construction d'un objet important pour le programme,
il y a échec, je dois détruire tous les objets créés auparavant afin de
quitter proprement.. celà demande toujours des tests ennuyeux, et de plus, la
liste de ces objets à détruire n'est jamais la même suivant l'endroit du
programme où l'erreur survient.

J'ai donc dans l'idée de programmer un petit gestionnaire d'erreur, je
pensais à un objet qui contiendrait la liste des objets crées (pointeurs)
ainsi qu'un pointeur vers leur destructeur respecif et un message char*
approprié (tel que le nom etc...)

ainsi lors d'une erreur, il serait "facile" de détruire un à un les objets
alloués en affichant ça à l'utilisateur... :

objet 1... détruit
objet 2... détruit
objet 3... détruit
...
objet n... détruit

Cependant je pense à une chose délicate, afin d'etre le plus général possible
mon gestionnaire ne doit pas accumuler une liste d'objets sans ordre... en
effet il se peut que certains objets soient dépendant d'autres, et que leur
destructeur requiert qu'un des autres objets soit encore en vie... il
faudrait donc une sorte d'arborescence d'objets à tuer...

Quelqu'un à -t-il déjà fait quelque chose de similaire ? avez-vous une/des
bonne(s) idée(s) à me proposer ?


En principe, si on utilise sytématiquement les constructeurs pour créer
et les destructeurs pour détruire, y compris en cas d'erreur, il n'y a
aucun problème. Il est cependant important de correctement gérer l'état
des pointeurs. Si ils sont ou si ils deviennent invalides, les forcer à
NULL.

http://mapage.noos.fr/emdel/tad.htm
http://mapage.noos.fr/emdel/clib.htm

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

.sig under repair

Avatar
nico
Jean-Marc wrote:

Hello,

Quand tu parles de quitter proprement, tu parles de revenir à un point
donné de ton progrmmame, ou bien de quitter réellement l'application?



informer, détruire, quitter..


Dans le dernier cas, le problème ne se pose pas vraiment, si ce n'est
pour des raisons esthétiques: C'est le système d'exploitation qui va de
toute façon libérer tout ce qui a été alloué, en tout cas c'est comme
cela que ça fonctionne sur les OS que je connais.



moué, alors premièrement oui, c'est esthétique (pas un code de 300
lignes inutiles et répétées concernant la destruction des objets), c'est
aussi plus facile à coder par la suite :

type_obj obj = type_new();
if(!!obj)
gestion_erreur_quit(CODE_TYPE)


=>
"une erreur est survenue dans la creation de l'objet _TYPE_OBJET_ le
programme ne peux continuer"

objet 1... détruit
objet 2... détruit
objet 3... détruit
...
objet n... détruit

Fin du programme...
<

Ainsi, il n'y a pas de fuite mémoire dans le programme suivant:

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
char *p;
p = malloc(1000);
return EXIT_SUCCESS;
}



berk


En embarqué, je ne sais pas si la mémoire allouée par malloc() est
aussi libérée à la fin de l'exécution du programme, je suppose que
c'est le cas également. Me trompe je ?




pas forcément, sinon le free ne servirait a rien

--
Nicolas Aunai
http:nicolas.auanai.free.fr

Avatar
nico
Emmanuel Delahaye wrote:

En principe, si on utilise sytématiquement les constructeurs pour créer
et les destructeurs pour détruire, y compris en cas d'erreur, il n'y a
aucun problème. Il est cependant important de correctement gérer l'état
des pointeurs. Si ils sont ou si ils deviennent invalides, les forcer à
NULL.




okay mais regarde :

typeA objA = typeA_new()
if(!objA)
return EXIT_FAILURE;


typeB objB = typeB_new()
if(!objB)
{
typeA_free(objA);
return EXIT_FAILURE;
}

typeC objC = typeC_new();
if(!objC)
{
typeA_free(objA);
typeB_free(objB);
return EXIT_FAILURE;
}


etc etc etc...
à chaque erreur eventuelle de construction, je dois détruire les objets
précédents, cette répétition de code m'agace, d'où l'idée d'avoir une
liste d'objets valides à détruire en cas d'erreur ...


question bonus
les prototypes de mes destructeurs sont tous identiques :

void type_free(type *)

comment déclare -t-on un pointeur de fonction générique sur ce genre de
prototype ?



--
Nicolas Aunai
http:nicolas.auanai.free.fr

Avatar
Jean-Marc
"nico" a écrit dans le message de
news:42bd1bc3$0$22315$

Ainsi, il n'y a pas de fuite mémoire dans le programme suivant:

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
char *p;
p = malloc(1000);
return EXIT_SUCCESS;
}



berk


Ben non, pas berk. Ca marche comme cela, c'est tout à fait
correct dans ce contexte de ne pas faire de free, celui ci est
inutile (ici).


En embarqué, je ne sais pas si la mémoire allouée par malloc() est
aussi libérée à la fin de l'exécution du programme, je suppose que
c'est le cas également. Me trompe je ?




pas forcément, sinon le free ne servirait a rien



Le free est utile dans bien d'autres contextes. Il permet de libérer la
mémoire allouée pendant l'exécution du programme et la réutilisation de
celle ci par le même programme, dans la même session d'exécution.
Si tu quittes réellement le programme, la désallocation est faite pour toi.
On peut discuter de l'esthétisme, mais c'est tout. Fonctionellement,
la libération explicite avant de quitter est inutile (je ne parle pas
de l'embarqué que je ne connais pas).

--
Jean-marc
"There are only 10 kind of people
those who understand binary and those who don't."


Avatar
nico
Jean-Marc wrote:

Le free est utile dans bien d'autres contextes. Il permet de libérer la
mémoire allouée pendant l'exécution du programme et la réutilisation de
celle ci par le même programme, dans la même session d'exécution.
Si tu quittes réellement le programme, la désallocation est faite pour toi.
On peut discuter de l'esthétisme, mais c'est tout. Fonctionellement,
la libération explicite avant de quitter est inutile (je ne parle pas
de l'embarqué que je ne connais pas).




bah ça me choque de quitter sans freeter, voilà tout. :-)


--
Nicolas Aunai
http:nicolas.auanai.free.fr

Avatar
Harpo
nico wrote:


bah ça me choque de quitter sans freeter, voilà tout. :-)


On ne va pas se friter pour ça : non ?

Avatar
Harpo
Jean-Marc wrote:


Ainsi, il n'y a pas de fuite mémoire dans le programme suivant:

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
char *p;
p = malloc(1000);
return EXIT_SUCCESS;
}


Il serait en principe complètement superflu de faire un free.
Je n'ai pas la même notion de l'esthétisme que vous, cela ne sert que si
on veut, à l'exit d'un programme savoir s'il y a de la mémoire non
libérée par inattention, par exemple en utilisant GNU mtrace().
Le fait de libérer, même sans interêt toute la mémoire allouée permet de
savoir que la mémoire qui n'a pâs été désallouée l'a été par oubli.

Cela n'a généralement pas une incidence énorme d'oublier de désallouer
la mémoire sans un programme qui lit un fichier et en écrit un autre an
magouillant les données au passage. Sur un serveur que l'on arrête à
chaque fois que l'on change de CPU, cela en a.

Pour moi, il s'agit plus de pragmatisme que d'esthétisme, liberer la
mémoire à la fin d'un programme n'a de sens que si on recherche les
raisons pour lesquelles la mémoire non désallouée ne l'a pas été.


En embarqué, je ne sais pas si la mémoire allouée par malloc()
est
aussi libérée à la fin de l'exécution du programme, je suppose
que c'est le cas également. Me trompe je ?


Si l'exit du programme correspond à la suppression de l'espace
d'adressage, je ne vois pas très bien comment ça pourrait ne pas
l'être.

Avatar
Pierre Maurette
nico wrote:


bah ça me choque de quitter sans freeter, voilà tout. :-)


On ne va pas se friter pour ça : non ?
On n'est pas là pour s'effriter ...

(mais c'est si bon ;-) )

--
Pour répondre directement: enlever une lettre sur deux
wwaannaaddoooo -> wanadoo

Pierre Maurette


Avatar
Stephane Legras-Decussy
nico a écrit dans le message :
42bd14aa$0$17123$
par exemple, lors de la construction d'un objet important pour le
programme, il y a échec, je dois détruire tous les objets créés
auparavant afin de quitter proprement.. celà demande toujours des tests
ennuyeux, et de plus, la liste de ces objets à détruire n'est jamais la
même suivant l'endroit du programme où l'erreur survient.


en initialisant tous les pointeurs d'objets à NULL
au départ, on faire une fonction freeall()
qui free tous les objets qu'ils aient été alloué ou non.

c'est brutal mais pourquoi pas ?

1 2 3