OVH Cloud OVH Cloud

std::bad_alloc

6 réponses
Avatar
Bruno CAUSSE
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. 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?

--
Bruno

6 réponses

Avatar
Fabien LE LEZ
On Wed, 25 May 2005 11:02:39 +0200, Bruno CAUSSE :

A ne lançant pas d'exception (bad_alloc)


C'est new qui lance l'exception.

Avatar
Bruno CAUSSE
dans l'article , Fabien LE LEZ à
a écrit le 25/05/05 11:17 :

C'est new qui lance l'exception.


Oui. Et ....?

Avatar
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

Avatar
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.


Avatar
Bruno CAUSSE
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.



Avatar
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