Try {
b = new B[10000000000];
} catch (std::bad_alloc &e_ba) {
cerr << "manque de mémoire";
throws;
}
C'est "probablement*" en essayant d'allouer un A que le manque de mémoire se
produira. A ne lançant pas d'exception (bad_alloc) le constructeur de C est
t'il correcte?
* a la limite un B mais c'est le même problème
Dois je redéfinir chaque constructeurs par défaut en gérant l'échec
d'allocation en lançant une bad°alloc?
En d'autre terme le "constructeur par defaut implicite" lance t'il une
exception en cas d'echec?
dans l'article , Fabien LE LEZ à a écrit le 25/05/05 11:17 :
C'est new qui lance l'exception.
Oui. Et ....?
Vincent Lascaux
Dois je redéfinir chaque constructeurs par défaut en gérant l'échec d'allocation en lançant une bad°alloc?
Je comprends pas vraiment ton problème... L'échec d'allocation est déjà géré tout seul en lançant une bad_alloc (puisque comme te le disait Fabien, new peut lancer une bad_alloc). Alors que veux tu faire de plus ?
En d'autre terme le "constructeur par defaut implicite" lance t'il une exception en cas d'echec?
C'est new qui lance une exception et non pas le constructeur... Quand tu fais new A(), en interne, ca alloue de la mémoire (genre un malloc), lance une exception bad_alloc s'il n'arrive pas à allouer la quantité nécessaire de mémoire, et ensuite appelle le constructeur de A. Le constructeur par défaut implicite ne lance donc une bad_alloc que si l'un des constructeur des variables membres en lance une.
-- Vincent
Dois je redéfinir chaque constructeurs par défaut en gérant l'échec
d'allocation en lançant une bad°alloc?
Je comprends pas vraiment ton problème... L'échec d'allocation est déjà géré
tout seul en lançant une bad_alloc (puisque comme te le disait Fabien, new
peut lancer une bad_alloc). Alors que veux tu faire de plus ?
En d'autre terme le "constructeur par defaut implicite" lance t'il une
exception en cas d'echec?
C'est new qui lance une exception et non pas le constructeur...
Quand tu fais new A(), en interne, ca alloue de la mémoire (genre un
malloc), lance une exception bad_alloc s'il n'arrive pas à allouer la
quantité nécessaire de mémoire, et ensuite appelle le constructeur de A. Le
constructeur par défaut implicite ne lance donc une bad_alloc que si l'un
des constructeur des variables membres en lance une.
Dois je redéfinir chaque constructeurs par défaut en gérant l'échec d'allocation en lançant une bad°alloc?
Je comprends pas vraiment ton problème... L'échec d'allocation est déjà géré tout seul en lançant une bad_alloc (puisque comme te le disait Fabien, new peut lancer une bad_alloc). Alors que veux tu faire de plus ?
En d'autre terme le "constructeur par defaut implicite" lance t'il une exception en cas d'echec?
C'est new qui lance une exception et non pas le constructeur... Quand tu fais new A(), en interne, ca alloue de la mémoire (genre un malloc), lance une exception bad_alloc s'il n'arrive pas à allouer la quantité nécessaire de mémoire, et ensuite appelle le constructeur de A. Le constructeur par défaut implicite ne lance donc une bad_alloc que si l'un des constructeur des variables membres en lance une.
-- Vincent
Fabien LE LEZ
On Wed, 25 May 2005 11:26:40 +0200, Bruno CAUSSE :
C'est new qui lance l'exception.
Oui. Et ....?
Et ce n'est donc pas A, ou B, ou ta grand-mère.
On Wed, 25 May 2005 11:26:40 +0200, Bruno CAUSSE <envoi@lesSpam.fr>:
dans l'article , Fabien LE LEZ à a écrit le 25/05/05 11:42 :
On Wed, 25 May 2005 11:26:40 +0200, Bruno CAUSSE :
C'est new qui lance l'exception.
Oui. Et ....?
Et ce n'est donc pas A, ou B, ou ta grand-mère.
Ok, new calcule l'espace necessaire pour stocker le tableau. Et lance l'exception en cas d'echec.
Je referai les tests ce soir, mais je n'attrapais pas l'exception d'ou ma question.
kanze
Bruno CAUSSE wrote:
Class A {....} Class B { A a1, A a2}
Une classe C qui a une variable d'instance B* b.
dans le constructeur
Try { b = new B[10000000000]; } catch (std::bad_alloc &e_ba) { cerr << "manque de mémoire"; throws; }
C'est "probablement*" en essayant d'allouer un A que le manque de mémoire se produira.
Tel que tu l'as écrit ci-dessus, les A font partie integrante des B ; il n'y a pas d'« allocation »> d'un A qui pourrait échouer.
A ne lançant pas d'exception (bad_alloc) le constructeur de C est t'il correcte?
Sauf que tu as écrit « throws », et non « throw ».
* a la limite un B mais c'est le même problème
Dois je redéfinir chaque constructeurs par défaut en gérant l'échec d'allocation en lançant une bad°alloc?
Un constructeur par défaut ne peut pas lever un bad_alloc. Seulement un new peut lever un bad_alloc (au moins que tu écris « throw std::bad_alloc » quelque part dans ton code à toi). Et un constructeur par défaut ne fait pas de new.
En d'autre terme le "constructeur par defaut implicite" lance t'il une exception en cas d'echec?
Un constructeur par défaut implicit ne connaît pas d'échec. Le problème ne se pose donc pas.
Enfin, c'est une simplification de ma part, parce que d'une part, le constructeur par défaut appelle des constructeurs de ses sous-objets, et ils peuvent bien appeler new, de de l'autre, il peut bien y avoir certains cas d'échec, propre au système. Mais à peu près la seule possibilité que je vois dans ce dernier cas, c'est un débordement de la pile, si le compilateur n'a pas généré le constructeur en ligne, et sur les systèmes que je connais, un débordement de la pile mène tout de suite à un core dump.
Note aussi qu'en cas d'une exception, on appelle le destructeur des objets déjà construits. Donc, si à la place de « A a1 », ton B contenait un « A* a1 », initialisé par un new dans le constructeur, et ce new lève un bad_alloc quelque part au milieu de la construction du tableau, le compilateur va appeler le destructeur de tous les objets construit auparavent. Et évidemment, dans le destructeur, on libère la mémoire acquise dans le constructeur. (Mais attention si le constructeur a deux new. Si le deuxième échoue, l'objet n'est pas encore construit, son déstructeur n'est pas appelé, et on risque de perdre la mémoire allouée par le premier. C'est pour ça qu'on utilise prèsqu'exclusivement des pointeurs intelligents dans ces cas-ci : soit std::auto_ptr, soit boost::scoped_ptr. Et qu'on n'alloue pas des tableaux comme ça, mais qu'on utilise plutôt std::vector.)
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Bruno CAUSSE wrote:
Class A {....}
Class B { A a1, A a2}
Une classe C qui a une variable d'instance B* b.
dans le constructeur
Try {
b = new B[10000000000];
} catch (std::bad_alloc &e_ba) {
cerr << "manque de mémoire";
throws;
}
C'est "probablement*" en essayant d'allouer un A que le manque
de mémoire se produira.
Tel que tu l'as écrit ci-dessus, les A font partie integrante
des B ; il n'y a pas d'« allocation »> d'un A qui pourrait
échouer.
A ne lançant pas d'exception (bad_alloc) le constructeur de C
est t'il correcte?
Sauf que tu as écrit « throws », et non « throw ».
* a la limite un B mais c'est le même problème
Dois je redéfinir chaque constructeurs par défaut en gérant
l'échec d'allocation en lançant une bad°alloc?
Un constructeur par défaut ne peut pas lever un bad_alloc.
Seulement un new peut lever un bad_alloc (au moins que tu écris
« throw std::bad_alloc » quelque part dans ton code à toi). Et
un constructeur par défaut ne fait pas de new.
En d'autre terme le "constructeur par defaut implicite" lance
t'il une exception en cas d'echec?
Un constructeur par défaut implicit ne connaît pas d'échec. Le
problème ne se pose donc pas.
Enfin, c'est une simplification de ma part, parce que d'une
part, le constructeur par défaut appelle des constructeurs de
ses sous-objets, et ils peuvent bien appeler new, de de l'autre,
il peut bien y avoir certains cas d'échec, propre au système.
Mais à peu près la seule possibilité que je vois dans ce dernier
cas, c'est un débordement de la pile, si le compilateur n'a pas
généré le constructeur en ligne, et sur les systèmes que je
connais, un débordement de la pile mène tout de suite à un core
dump.
Note aussi qu'en cas d'une exception, on appelle le destructeur
des objets déjà construits. Donc, si à la place de « A a1 »,
ton B contenait un « A* a1 », initialisé par un new dans le
constructeur, et ce new lève un bad_alloc quelque part au milieu
de la construction du tableau, le compilateur va appeler le
destructeur de tous les objets construit auparavent. Et
évidemment, dans le destructeur, on libère la mémoire acquise
dans le constructeur. (Mais attention si le constructeur a deux
new. Si le deuxième échoue, l'objet n'est pas encore construit,
son déstructeur n'est pas appelé, et on risque de perdre la
mémoire allouée par le premier. C'est pour ça qu'on utilise
prèsqu'exclusivement des pointeurs intelligents dans ces
cas-ci : soit std::auto_ptr, soit boost::scoped_ptr. Et qu'on
n'alloue pas des tableaux comme ça, mais qu'on utilise plutôt
std::vector.)
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Try { b = new B[10000000000]; } catch (std::bad_alloc &e_ba) { cerr << "manque de mémoire"; throws; }
C'est "probablement*" en essayant d'allouer un A que le manque de mémoire se produira.
Tel que tu l'as écrit ci-dessus, les A font partie integrante des B ; il n'y a pas d'« allocation »> d'un A qui pourrait échouer.
A ne lançant pas d'exception (bad_alloc) le constructeur de C est t'il correcte?
Sauf que tu as écrit « throws », et non « throw ».
* a la limite un B mais c'est le même problème
Dois je redéfinir chaque constructeurs par défaut en gérant l'échec d'allocation en lançant une bad°alloc?
Un constructeur par défaut ne peut pas lever un bad_alloc. Seulement un new peut lever un bad_alloc (au moins que tu écris « throw std::bad_alloc » quelque part dans ton code à toi). Et un constructeur par défaut ne fait pas de new.
En d'autre terme le "constructeur par defaut implicite" lance t'il une exception en cas d'echec?
Un constructeur par défaut implicit ne connaît pas d'échec. Le problème ne se pose donc pas.
Enfin, c'est une simplification de ma part, parce que d'une part, le constructeur par défaut appelle des constructeurs de ses sous-objets, et ils peuvent bien appeler new, de de l'autre, il peut bien y avoir certains cas d'échec, propre au système. Mais à peu près la seule possibilité que je vois dans ce dernier cas, c'est un débordement de la pile, si le compilateur n'a pas généré le constructeur en ligne, et sur les systèmes que je connais, un débordement de la pile mène tout de suite à un core dump.
Note aussi qu'en cas d'une exception, on appelle le destructeur des objets déjà construits. Donc, si à la place de « A a1 », ton B contenait un « A* a1 », initialisé par un new dans le constructeur, et ce new lève un bad_alloc quelque part au milieu de la construction du tableau, le compilateur va appeler le destructeur de tous les objets construit auparavent. Et évidemment, dans le destructeur, on libère la mémoire acquise dans le constructeur. (Mais attention si le constructeur a deux new. Si le deuxième échoue, l'objet n'est pas encore construit, son déstructeur n'est pas appelé, et on risque de perdre la mémoire allouée par le premier. C'est pour ça qu'on utilise prèsqu'exclusivement des pointeurs intelligents dans ces cas-ci : soit std::auto_ptr, soit boost::scoped_ptr. Et qu'on n'alloue pas des tableaux comme ça, mais qu'on utilise plutôt std::vector.)
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34