OVH Cloud OVH Cloud

Exception multiples

114 réponses
Avatar
bernard tatin
J'ai un problème d'exceptions multiples qui, je pense, est bien décrit
par le code suivant :

// une exception
class Excp {
public:
Excp(char *msg) : message (msg) {}
virtual ~Excp() {}
inline string& getMessage () {
return message;
}
protected:
string message;
};

// une classe simple
class B {
public:
B(int j) : k(j) {}
inline void run () {
throw Excp("exception imprévue dans le run");
}
virtual ~B () { throw Excp("Bad B"); }
private:
int k;
};

void test_excp () {
try {
try {
B b(-5);
b.run();
std::cout << "Création de B ... et sortie" << std::endl;
}
catch (Excp &e) {
std::cout << "Exception " << e.getMessage() << std::endl;
}
}
catch (Excp &e) {
std::cout << "Exception " << e.getMessage() << std::endl;
}
catch (...) {
std::cout << "Exception inconnue" << std::endl;
}
}

int main () {
test_excp ();
return 0;
}

Je comprend que l'exception déclenchée dans b.run() provoque la sortie
du bloc et donc la destruction de l'objet b. Une nouvelle exception est
alors levée. Je pensais que mes try/catch résolverais le problème, mais
ce n'est pas le cas. J'ai un message
Executable “tests” has exited due to signal 6 (SIGABRT).
Et rien d'autre. C'est un vrai plantage. Si je supprime l'un des deux
throw, j'ai le résultat attendu.

J'utilise gcc 3.3 sur MacOS 10.3.5.

Est-ce que quelqu'un a des explications ? Je sais comment m'en dépétrer,
ce qui m'intéresse c'est le pourquoi du comment.

Merci.

Bernard.

10 réponses

8 9 10 11 12
Avatar
Jean-Marc Bourguet
drkm writes:

(Daveed Vandevoorde) writes:

Si le template change, le modele d'inclusion voit tous
les "translation units" qui inclue ce template affecte.
Eviter les recompilations superflue est nettement plus
difficile dans ce cas (probablement plus complexe que
l'implementation d'export). Avec export, seulement le
"translation unit" contenant la template doit etre
recompile et les instantiations base sur cette template
doivent etre recree (mais ca peut ce faire a partir
d'une ou plusieurs "translation unit" deja compile).


Donc si je comprends bien, si un template exporté
change, on n'a pas besoin des sources des TUs qui
l'utilisent, juste des fichiers objet de ces TUs ?


En théorie on n'en a pas besoin.

En pratique, pour le moment avec como et avec intel -- et
pour autant que je n'ai pas manqué une option -- il faut les
sources. Mais un seul d'entre eux est recompilé.
Exemple:

$ cat main.cxx
void use1();
void use2();

int main()
{
use1();
use2();
}
$ cat use1.cxx
#include "func.hxx"
#include "type.hxx"

void use1()
{
func<type>();
}
$ cat use2.cxx
#include "func.hxx"
#include "type.hxx"

void use2()
{
func<type>();
}
$ cat func.hxx
#ifndef FUNC_HXX_INCLUDED
#define FUNC_HXX_INCLUDED

#if defined(USE_EXPORT)
#define EXPORT export
#else
#define EXPORT
#endif

EXPORT template <typename T>
void func();

#if not defined(USE_EXPORT)
#include "func.cxx"
#endif

#endif
$ cat func.cxx
#include "func.hxx"

template <typename T>
void func()
{
}
$ cat type.hxx
#ifndef TYPE_HXX_INCLUDED
#define TYPE_HXX_INCLUDED

class type
{
};

#endif
$ cat Makefile
CXX=icpc
CXXFLAGS=-export
CPPFLAGS=-DUSE_EXPORT
OBJECTS=main.o use1.o use2.o func.o

all: test

.SUFFIXES: .cxx
.cxx.o:
$(CXX) $(CXXFLAGS) -c $(CPPFLAGS) -M $< > $*.d
$(CXX) $(CXXFLAGS) -c $(CPPFLAGS) -o $@ $<

test: $(OBJECTS)
$(CXX) $(CXXFLAGS) -o test $(OBJECTS)

clean:
-rm test *.o *.d *.ti *.pch *.ii *.et *.tii

-include *.d
$ make clean
rm test *.o *.d *.ti *.pch *.ii *.et *.tii
rm: Ne peut enlever `*.pch': Aucun fichier ou répertoire de ce type
rm: Ne peut enlever `*.ii': Aucun fichier ou répertoire de ce type
make: [clean] Erreur 1 (ignorée)
$ make
icpc -export -c -DUSE_EXPORT -M main.cxx > main.d
icpc -export -c -DUSE_EXPORT -o main.o main.cxx
icpc -export -c -DUSE_EXPORT -M use1.cxx > use1.d
icpc -export -c -DUSE_EXPORT -o use1.o use1.cxx
icpc -export -c -DUSE_EXPORT -M use2.cxx > use2.d
icpc -export -c -DUSE_EXPORT -o use2.o use2.cxx
icpc -export -c -DUSE_EXPORT -M func.cxx > func.d
icpc -export -c -DUSE_EXPORT -o func.o func.cxx
icpc -export -o test main.o use1.o use2.o func.o
C++ prelinker: void func<type>() assigned to file use1.o
C++ prelinker: executing: icpc -long_double -export -DUSE_EXPORT -c -o use1.o use1.cxx
$ touch func.cxx
$ make
icpc -export -c -DUSE_EXPORT -M func.cxx > func.d
icpc -export -c -DUSE_EXPORT -o func.o func.cxx
icpc -export -o test main.o use1.o use2.o func.o
C++ prelinker: rebuilding use1.o because func.cxx (used by an exported template file) has changed
C++ prelinker: executing: icpc -long_double -long_double -export -DUSE_EXPORT -c -o use1.o use1.cxx
$ touch type.hxx
$ make
icpc -export -c -DUSE_EXPORT -M use1.cxx > use1.d
icpc -export -c -DUSE_EXPORT -o use1.o use1.cxx
icpc -export -c -DUSE_EXPORT -M use2.cxx > use2.d
icpc -export -c -DUSE_EXPORT -o use2.o use2.cxx
icpc -export -o test main.o use1.o use2.o func.o
C++ prelinker: void func<type>() no longer needed in use1.o
C++ prelinker: executing: icpc -long_double -export -DUSE_EXPORT -c -o use1.o use1.cxx

(A part qu'il y a un problème use1.o a toujours besoin void
func<type>() -- c'est même pire qu'un problème de message,
parce que si on retouche func.cxx on recompile use1 et use2
-- nouveau bug report à intel. Mais çe bug est absent de
chez como).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
drkm
Jean-Marc Bourguet writes:

drkm writes:

(Daveed Vandevoorde) writes:

Si le template change, le modele d'inclusion voit tous
les "translation units" qui inclue ce template affecte.
Eviter les recompilations superflue est nettement plus
difficile dans ce cas (probablement plus complexe que
l'implementation d'export). Avec export, seulement le
"translation unit" contenant la template doit etre
recompile et les instantiations base sur cette template
doivent etre recree (mais ca peut ce faire a partir
d'une ou plusieurs "translation unit" deja compile).


Donc si je comprends bien, si un template exporté
change, on n'a pas besoin des sources des TUs qui
l'utilisent, juste des fichiers objet de ces TUs ?


En théorie on n'en a pas besoin.

En pratique, pour le moment avec como et avec intel -- et
pour autant que je n'ai pas manqué une option -- il faut les
sources. Mais un seul d'entre eux est recompilé.


[exemple complet ; merci]

J'imagine qu'il y a quelque chose comme un stockage de
l'instantiation dans une des TUs traduites. Il devrait être facile
d'utiliser à la place une sorte de repository pour ne plus du tout
avoir besoin des sources des TUs utilisatrices.

(A part qu'il y a un problème use1.o a toujours besoin void
func<type>() -- c'est même pire qu'un problème de message,
parce que si on retouche func.cxx on recompile use1 et use2
-- nouveau bug report à intel. Mais çe bug est absent de
chez como).


Je ne comprend pas ce paragraphe.

--drkm



Avatar
Jean-Marc Bourguet
drkm writes:

Jean-Marc Bourguet writes:

drkm writes:

(Daveed Vandevoorde) writes:

Si le template change, le modele d'inclusion voit tous
les "translation units" qui inclue ce template affecte.
Eviter les recompilations superflue est nettement plus
difficile dans ce cas (probablement plus complexe que
l'implementation d'export). Avec export, seulement le
"translation unit" contenant la template doit etre
recompile et les instantiations base sur cette template
doivent etre recree (mais ca peut ce faire a partir
d'une ou plusieurs "translation unit" deja compile).


Donc si je comprends bien, si un template exporté
change, on n'a pas besoin des sources des TUs qui
l'utilisent, juste des fichiers objet de ces TUs ?


En théorie on n'en a pas besoin.

En pratique, pour le moment avec como et avec intel -- et
pour autant que je n'ai pas manqué une option -- il faut les
sources. Mais un seul d'entre eux est recompilé.


[exemple complet ; merci]

J'imagine qu'il y a quelque chose comme un stockage de
l'instantiation dans une des TUs traduites.


Exact.

Il devrait être facile d'utiliser à la place une sorte de
repository pour ne plus du tout avoir besoin des sources
des TUs utilisatrices.


Il faut alors stocker suffisemment du contexte
d'instantiation pour pouvoir instantier le template. Et
sans les sources du template, c'est difficile de savoir ce
dont on a besoin.

(A part qu'il y a un problème use1.o a toujours besoin void
func<type>() -- c'est même pire qu'un problème de message,
parce que si on retouche func.cxx on recompile use1 et use2
-- nouveau bug report à intel. Mais çe bug est absent de
chez como).


Je ne comprend pas ce paragraphe.


Le message

C++ prelinker: void func<type>() no longer needed in use1.o

est faux. En fait il est vrai parce que l'instantiation est
maintenant assignée à use2.o, mais il y a un bug parce que
on refait
$ touch func.cxx
$ make
on se trouve à recompiler use1.o et use2.o. Il y a
maintenant un rapport chez Intel à ce sujet. Le problème
n'existe pas si on utilise Como.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org




Avatar
drkm
Jean-Marc Bourguet writes:

drkm writes:

Il devrait être facile d'utiliser à la place une sorte de
repository pour ne plus du tout avoir besoin des sources
des TUs utilisatrices.


Il faut alors stocker suffisemment du contexte
d'instantiation pour pouvoir instantier le template. Et
sans les sources du template, c'est difficile de savoir ce
dont on a besoin.


Heu, je ne suis plus sûr que nous parlons de la même chose. Si l'on
modifie le modèle, il me semble clair qu'on doit en disposer des
sources. Pour moi, c'était des TUs utilisatrices (qui utilisent une
instance du modèle) que l'on pouvait se passer.

--drkm


Avatar
Jean-Marc Bourguet
drkm writes:

Jean-Marc Bourguet writes:

drkm writes:

Il devrait être facile d'utiliser à la place une sorte de
repository pour ne plus du tout avoir besoin des sources
des TUs utilisatrices.


Il faut alors stocker suffisemment du contexte
d'instantiation pour pouvoir instantier le template. Et
sans les sources du template, c'est difficile de savoir ce
dont on a besoin.


Heu, je ne suis plus sûr que nous parlons de la même chose. Si
l'on modifie le modèle, il me semble clair qu'on doit en disposer
des sources. Pour moi, c'était des TUs utilisatrices (qui utilisent
une instance du modèle) que l'on pouvait se passer.


Si tu veux te passer des sources des TU utilisatrices, il faut que tu
ai garde suffisemment du contexte d'instanciation pour savoir ce dont
le template a besoin (ce n'est pas tout le contexte, car on ne peut y
trouver que des noms dependants, mais ca peut faire quand meme
beaucoup).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
drkm
Jean-Marc Bourguet writes:

drkm writes:

Jean-Marc Bourguet writes:

Il faut alors stocker suffisemment du contexte
d'instantiation pour pouvoir instantier le template. Et
sans les sources du template, c'est difficile de savoir ce
^^^^^^^^^^^^^^^^^^^^^^^



dont on a besoin.


Heu, je ne suis plus sûr que nous parlons de la même chose. Si
l'on modifie le modèle, il me semble clair qu'on doit en disposer
des sources. Pour moi, c'était des TUs utilisatrices (qui utilisent
une instance du modèle) que l'on pouvait se passer.


Si tu veux te passer des sources des TU utilisatrices, il faut que tu
ai garde suffisemment du contexte d'instanciation pour savoir ce dont
le template a besoin (ce n'est pas tout le contexte, car on ne peut y
trouver que des noms dependants, mais ca peut faire quand meme
beaucoup).


Ok, donc tu parlais ci-dessus des sources des TUs utilisatrices.

Et lorsque tu dis « pour savoir ce dont le template a besoin », je
suppose que tu penses « pour savoir ce dont on a besoin du template ».

Mais à part les paramètres d'instanciation et la liste des membres
utilisés (dans le cas d'un modèle de classe), quelle information du
contexte est ici intéressante (pour envisager l'utilisation d'un
repository d'instances de modèles) ?

--drkm



Avatar
Jean-Marc Bourguet
drkm writes:

Mais à part les paramètres d'instanciation et la liste des membres
utilisés (dans le cas d'un modèle de classe), quelle information du
contexte est ici intéressante (pour envisager l'utilisation d'un
repository d'instances de modèles) ?


Pour instantier un template, tu as besoin
- de la definition du template
- du contexte d'instantiation.

Ce dernier contient en plus des parametres template explicites, les
parametres templates implicites que sont les noms dependants.

C'est ces derniers auxquels je faisais allusion. Tu ne peux pas te
permettre de ne stocker que les noms dependants utilises: tu ne les
connais pas et ca peut changer si la definition du template change.
Et les trouver tous n'est vraissemblablement pas simple et efficace
avec une table de symbole pas concue pour ca (et comme il n'y a pas
d'autres utilisations dans un compilateur, il est douteux que la table
des symboles ait ete concue avec cet usage en vue -- les tables de
symboles sont concues pour cherches les declarations et les
definitions d'un nom, pas les declarations et les definitions
utilisant un nom).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
google
drkm wrote:
Jean-Marc Bourguet writes:
[...]

J'imagine qu'il y a quelque chose comme un stockage de
l'instantiation dans une des TUs traduites. Il devrait être facile
d'utiliser à la place une sorte de repository pour ne plus du tout
avoir besoin des sources des TUs utilisatrices.


"Facile" est un concepte relatif ;-) Mais, oui c'est possible.
En fait, le produit C++ d'EDG peut etre configure pour
generer les instantiations dans des fichiers objets separes.

Comme le mentionne Jean-Marc il faudrait en plus de ca
des fichiers representants les contextes des different TU.
C'est tout a fait possible (en faite, c'est plus ou moins une
version reduite des en-tetes precompiles, mais contrairement
aux en-tetes, il n'y a pas de problemes d'ordre puisque
chaque fichier represente un TU entier).

David

Avatar
drkm
Jean-Marc Bourguet writes:

C'est ces derniers auxquels je faisais allusion. Tu ne peux pas te
permettre de ne stocker que les noms dependants utilises: tu ne les
connais pas et ca peut changer si la definition du template change.


Ok. Je comprend mieux, maintenant. En effet, ça complique les
choses.

--drkm

Avatar
drkm
(Daveed Vandevoorde) writes:

"Facile" est un concepte relatif ;-)


En effet.

Je n'avais pas pensé au problème de la liste des noms dépendants qui
peut évoluer en même temps que le modèle. Ce qui nécessite bien plus
d'informations (et bien moins précisément identifiées, si je comprend
bien) du contexte d'instanciation que je ne l'imaginais au départ.

Il faut vraiment que je trouve le temps de lire ton bouquin ;-).

--drkm

8 9 10 11 12