IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

bloc try catch dans le main, est-ce le diable?


Sujet :

C++

  1. #1
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut bloc try catch dans le main, est-ce le diable?
    Bonjour tout le monde,

    je suis en train de me remettre au c++ après un gros détour vers d'autres langages plus... lents, on va dire

    Et là je tombe sur une question existentielle. Je vous explique:
    Je fais un petit programme. Il va comporter 3 classes de taille moyenne, ainsi que quelques petites fonctions et structures utilitaires. Ce programme est un "one shot": on le lance dans une console cmd, il fait des trucs, il génère son résultat, puis il se ferme.

    Les trois classes en question accèdent à des ressources fortement susceptibles de générer des exceptions lors de leur accès. Heureusement pour moi, je peux me permettre d'accéder à ces ressources une fois, récupérer ce dont j'ai besoin, puis libérer cette ressource. Ces ressources sont des fichiers, de la base de donnée, et quelques appels à des web services.

    Donc, j'ai opté pour du RAII: pour chacune de ces 3 classes, c'est lors de l'appel au constructeur que je récupère les données dont j'ai besoin. Et c'est là que j'ai un gros doute, car du coup, mon main() ressemble à ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    int main(int argc, char** argv)
    {
    	//... gestion des paramètres d'entrée
     
    	try
    	{
    		GIS_Reader reader( argv[1] );
    		GIS_XemManager xem_manager( argv[2] );
    		GIS_Computer computer( reader, xem_manager );
     
    		computer.Compute();
    	}
    	catch( exception & ex )
    	{
    		// message d'erreur
    	}
    }
    Ce qui me turlupine, c'est ce groc bloc try/catch dans le main. Depuis toujours, il me semblait que ce genre de pratique c'était très mal, mais aujourd'hui je suis incapable de dire pourquoi. Et cette façon de faire me convient particulièrement, au moins dans ce cas là: un petit programme qu'on lance une fois, dont l'exécution est rapide (quelques secondes normalement), et que si ça marche pas, on veut juste savoir pourquoi et relancer la commande.

    Donc voilà, c'était juste pour savoir si vous savez pourquoi ce type de pratique est déconseillée, et si dans mon cas ça peut vraiment poser des problèmes.


    Cordialement.
    r0d.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  2. #2
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Hello

    Je pense que c'est vu comme une mauvaise technique dans le sens où c'est la technique du paresseux. L'interception d'exception doit pouvoir permettre la reprise sur erreur (si elle est possible), et cette reprise se fait bien rarement dans le main. Il faut aussi faire gaffe à libérer les éventuelles ressources consommées par l'objet avant le lancement de l'exception, mais je pense que ce cas ne te concerne pas.

    Donc dans ton cas, ça ne me choque pas du tout. A ta place, je ne m'emmerderai pas et je continuerai comme ça.
    Find me on github

  3. #3
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    S'il n'y a qu'un try/catch dans le main, je dirais qu'on a opté pour la version pauvre de la gestion d'erreurs : On affiche un message "désolé" avant de planter. Ce qui peut être suffisant dans certains contextes (utilitaire en ligne de commande).

    Par contre, ne pas avoir de try/catch dans le main me semblerait suspect : On ne fourni même pas ce service minimal, en dernier recours.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Je ne trouve pas cela spécialement choquant. En fait, pas mal de frameworks utilisent ce genre de fonction main() englobée dans un try... catch (parfois plusieurs, même).

    J'y vois deux intérêts
    1- cela permet d'intercepter d'éventuelles exceptions non gérées. Normalement, il ne devrait pas y en avoir, mais un programme fonctionne rarement normalement, surtout au début. Ces erreurs imprévisibles sont souvent les plus difficiles à débuguer. La clause catch peut aider à les corriger, en remontant des informations sur l'état du programme juste avant sa sortie.

    2- cela permet, en cas de gros problème, de prendre d'éventuelles mesures conservatoires, sauvegarde de données, fermeture de ports, écriture de logs

    Mais comme d'autres l'ont dit, cela ne te dispense pas de gérer les exceptions dans le reste du programme. C'est une sorte de dernier recours.

    Francois

  5. #5
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    S'il n'y a qu'un try/catch dans le main, je dirais qu'on a opté pour la version pauvre de la gestion d'erreurs : On affiche un message "désolé" avant de planter. Ce qui peut être suffisant dans certains contextes (utilitaire en ligne de commande).

    Par contre, ne pas avoir de try/catch dans le main me semblerait suspect : On ne fourni même pas ce service minimal, en dernier recours.
    De même, j'ai pas mal étudié la question pour un jeu où j'ai du mettre en place toute une stratégie pour recouvrer de certaines érreurs et passser dans cerains processus pour les autres (comme m'envoyer un mail avec le log, etc.) mais j'en arrive toujours au même point où si je veux être sur d'avoir fait le maximum pour avoir les infos sur ce qu'il s'est passé, le minimum syndical est d'avoir ce dernier try/catch dans le main pour une tentative désespérée de log.

  6. #6
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Merci pour vos interventions.
    Mais j'avoue que j'ai encore du mal à comprendre ce qui se passe "en dessous du capot" avec les exceptions.

    Par exemple, est-ce que ça a un coût en terme de performance ce try/catch dans le main? Puisque finalement, l'intégralité du code est inclu dedans.

    Autre question (je reviens aux bases, j'espère que vous ne m'en tiendrez pas rigueur, mais je pense que ce n'est pas mauvais de le faire de temps en temps): en testant un peu mon programme dans le but de prévoir un peu les différent types d'erreurs à gérer, j'ai généré un dépassement d'index sur un vector. Et en fait, ce dépassement d'index (je ne suis pas sûr que ce soit le bon terme) génère une exception qui n'est pas récupérée par mon catch. Comment se fait-ce?

    Je comprend d'autant moins ce qu'il se passe car si j'utilise vector::at(index) à la place de l'opérateur[], je racupère bien mon "out of range" exception.

    note: je travaille en x64/release.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par r0d Voir le message
    Et en fait, ce dépassement d'index (je ne suis pas sûr que ce soit le bon terme) génère une exception qui n'est pas récupérée par mon catch. Comment se fait-ce?

    Je comprend d'autant moins ce qu'il se passe car si j'utilise vector::at(index) à la place de l'opérateur[], je racupère bien mon "out of range" exception.
    C'est normal.
    La méthode at() lance une exception, mais pas l'opérateur [].

    Voir CPlusPlus.com au sujet de la méthode at() :

    The difference between this member function and member operator function operator[] is that vector::at signals if the requested position is out of range by throwing an out_of_range exception.

    Il faut choisir entre sécurité et rapidité.

  8. #8
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Citation Envoyé par r0d Voir le message
    Merci pour vos interventions.
    Mais j'avoue que j'ai encore du mal à comprendre ce qui se passe "en dessous du capot" avec les exceptions.

    Par exemple, est-ce que ça a un coût en terme de performance ce try/catch dans le main? Puisque finalement, l'intégralité du code est inclu dedans.
    Il y a un cout :

    - en taille de binaire, parcequ'il faut bien que le code qui remonte l'exception soit inclus dans le binaire;
    - en rapidité d'exécution, mais c'est négligeable tant qu'une exception n'est pas levée, et si elle l'est alors de toutes manières c'est exceptionel. Autrement dit, a ne pas utiliser pour faire de la logique d'application, sinon il y aura au moins les perfs qui seront désastreuses.

    Il me semble que quelqu'un ici avait, lors d'une grosse discussion sur les exception, fait la comparaison avec ou sans exceptions et avait bien du admettre qu'il y a quand même un cout à l'execution "normale". Cela étant dit, faut de sacrées bonnes raisons pour ne pas vouloir payer le prix, comme par exemple bosser sur certains hardwares (voir ma réponse à cette question : http://programmers.stackexchange.com.../113481#113481 )

  9. #9
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    at() est très rarement utilisé.
    S'il y a une erreur de programmation/algo qui résulte sur un dépassement d'index, une exception n'est de toutes façons pas les bonne solution. L'idéal est une assertion dans ces conditions. Des implémentations de op[] pourraient le faire, ça reste assez rare malheureusement. Même quand notre implémentation de la SL est chechée, et que l'on active les checks, j'ai plutôt vu passer des exceptions pour l'instant.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  10. #10
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Citation Envoyé par Klaim Voir le message
    - en rapidité d'exécution, mais c'est négligeable tant qu'une exception n'est pas levée, et si elle l'est alors de toutes manières c'est exceptionel. Autrement dit, a ne pas utiliser pour faire de la logique d'application, sinon il y aura au moins les perfs qui seront désastreuses.

    [...]avait bien du admettre qu'il y a quand même un cout à l'execution "normale".
    Le surcout des exceptions c'est quand on est au pays magique sans erreurs : aucun code d'erreur n'est remonté, aucun test pour vérifier les codes d'erreurs, etc.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  11. #11
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par r0d Voir le message
    Par exemple, est-ce que ça a un coût en terme de performance ce try/catch dans le main? Puisque finalement, l'intégralité du code est inclu dedans.
    En fait, pas tout à fait... Ce que ta boucle try/catch dans le main dit, c'est que si l'une des trois fonctions que tu y appelles renvoie une exception, il faut la traiter, pas que chaque ligne de ton code renvoie des exceptions.

    En fait, les exceptions ne se produisent que quand on leur dit de le faire (throw). Elle remontent alors dans la hierarchie d'appels de ton programme, jusqu'à rencontrer un catch, éventuellement jusqu'à ton main().

    Ce qui a un cout en terme de performance, ce n'est pas la gestion de l'exception (la boucle try/catch) mais le controle qui déclenche, au niveau le plus bas, l'exception. Pour un vecteur, tester le dépassement à chaque accès est affreusement couteux, c'est pour cela que [] ne le fait pas. Si tu en as besoin at() le fait...

    Francois

  12. #12
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    Le surcout des exceptions c'est quand on est au pays magique sans erreurs : aucun code d'erreur n'est remonté, aucun test pour vérifier les codes d'erreurs, etc.
    Pour être clair :

    1. je n'ai pas fait le test moi même, mais il semble facile à faire et d'autres disent avoir eu le même résultat, sur le même compilo, a savoir VS2008 je crois, maisil faudrait retrouver le thread.
    2. l'idée c'était que le même code, sans code d'exception apparent et n'utilisant pas la STL, était chronométtré un poil plus lent avec l'option de compilation normale qu'avec l'option "pas d'exception" (et peut être aussi pas de RTTI?)

    Donc en gros, je ne fais que rapporter le résultat d'un test que je n'ai pas fait moi même, mais je pense que si tu t'y connais vachement en exceptions tu pourrais (ou moi si tout a coup je prends mon courage a deux mains) faire une appli toute bete de test et voir si effectivement ça a un impact dans le comportement tout à fait normal de l'application, avec une application correcte et qui ne fait pas d'erreur (donc il faut qu'elle soit très simple).

    Je vais pas avoir le temps d'en monter une aujourd'hui mais ce sujet m'interesse.

  13. #13
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    C'est le même principe que pour "list ou vector que choisir?".
    Il y a un seuil de gestion de tests de problèmes potentiels (hum ... c'est mal dit ça ... "points de rupture possibles dans le flot d'une fonction" disons) au delà duquel les exceptions vont écraser les codes de retours.
    Et un autre seuil sur le ratio d'opérations versus opérations pouvant échouer qui vont faire que la différence sera négligeable.


    C'est sûr que si le programme de bench est une malheureuse boucle avec un seul point de rupture, les exceptions peuvent paraitre plus chères.
    Prends un vrai programme avec des appels sur 2-3 niveaux de profondeur, et des fonctions qui en appellent plusieurs qui peuvent échouer. Et n'oublie pas les codes de retour. Je t'autorise (:p) à exploiter le stack unwinding plutôt que le SESE -- même si les code pro-code-de-retour tendent à être SESE, ou envahis d'arbres if-else.
    Là, tu as un vrai benchmark, que j'ai bidouillé pour montrer ma vérité : que les exceptions sont plus rapides dans des codes robustes.

    Au pays magique des erreurs qui n'existent pas. Evidemment qu'elles coutent cher! (Vu qu'elles rajoutent du code pour gérer des choses qui ne le sont pas habituellement)

    Pour un ensemble de lectures:
    - http://www.codeproject.com/KB/cpp/cp...oetcontra.aspx
    - http://lazarenko.me/tips-and-tricks/...nd-performance
    - http://stackoverflow.com/questions/3...es-in-c#307716
    - http://ra3s.com/wordpress/dysfunctio...tion-handling/
    - http://www.gamedev.net/page/resource...-handling-r953
    - http://www.developpez.net/forums/d36...n-performance/
    - http://blog.emmanueldeloget.com/inde...xceptionnelles
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  14. #14
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    On est d'accord, c'est pour ça que je développe mes jeux avec exception (sauf sur embarqué).

    Note toutefois que je n'ai pas parlé de valeurs de retours, moi je parle du cas où il n'y a pas de vérification d'érreur du tout - on pars du principe que le programme livré doit être correct ou suffisament correct pour un temps d'execution relativement long. Typiquement les jeux sur console.

  15. #15
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Alors pour moi il y a confusion entre erreur (codage -> assertions) et problème dans le contexte (sockets anormalement fermées, fichiers/I/O corrompus, saisies invalides, RAM saturée (éventuellement grâce à d'autres softs qui fuient) ... -> exceptions).
    Je ne peux pas dire pour les jeux, mais dans mon secteur, les problèmes exceptionnels ne doivent en aucun cas être ignorés.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  16. #16
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Pour les jeux sur console, en gros le constructeur va faire une batterie de tests qui suggèrent que le moindre crash ou blocage du jeu (dans sa logique ou même juste un freeze visuel, même temporaire) provoquera le refu de publication du jeu sur la plateforme.

    Ce qui fait qu'on se retrouve avec énormément d'assertions (qui crashent purement et simplement dans les tests) qui sautent toutes une fois sur la plateforme cible, même pour les tests internes. Parcequ'on a juste pas le droit de planter ET que les évènements spéciaux liés au hardware ne sont pas des exceptions mais des callbacks (comme fermer une DS en plein jeu).

    Du coup, pas d'environnement avec exceptions.

    Contrairement aux mobiles, même pré-IPhone, où effectivement il ya un interet à avoir des exceptions parcequ'on maitrise moins l'environnement d'execution que sur console.


    L'autre cas c'est sur PC où on peut remplacer certaines assertions par par exemple des elements visuels incorrects de manière évidente (un cube fushia indiquant que le mesh a afficher n'a pas été trouvé), ça peut s'appliquer aussi sur console mais dans ce cas on passe par des codes d'erreurs, et on le fait aussi rarement que possible.

Discussions similaires

  1. Réponses: 10
    Dernier message: 06/10/2010, 17h06
  2. Visibilité de mon tableau dans bloc try catch
    Par erox44 dans le forum Collection et Stream
    Réponses: 1
    Dernier message: 18/05/2010, 15h13
  3. Faire un return dans un bloc try catch
    Par alizee971 dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 13/08/2008, 19h38
  4. Problème try-catch dans mon code
    Par little pepito dans le forum Langage
    Réponses: 7
    Dernier message: 11/06/2007, 12h22
  5. Try catch dans une dll - possible ?
    Par Pendary dans le forum C++Builder
    Réponses: 1
    Dernier message: 02/03/2007, 16h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo