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 :

Question sur les problèmes d'allocation dynamique


Sujet :

C++

  1. #1
    Membre habitué

    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 137
    Points : 161
    Points
    161
    Par défaut Question sur les problèmes d'allocation dynamique
    Bonjour,

    Une question me trotte dans la tête depuis un moment.
    Je lis souvent qu'une allocation dynamique peut échouer.

    Perso, je prends toujours pour hypothèse que tout se passera bien (sauf si je veux une "grosse" zone mémoire). En tout cas, je n'ai jamais constaté ce genre de problème dans mes programmes.

    Je pense que ça devient vite ingérable si il faut controler à chaque fois. En plus, on aura tendance dans ce cas à faire une sur-utilisation de la pile (dites-moi si je dis n'importe quoi ).

    Quand faut-il faire une vérification et pourquoi ?

    Merci,
    Sly.

  2. #2
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    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 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Quand ? il faut toujours se préoccuper de ces problèmes. (je ne dis pas "vérifier le succès des allocations"!)

    Pourquoi ? Murphy veille. Et si jamais un tel problème survient à un endroit où l'on ne pensait pas qu'il surviendrait, on va perdre un temps fou à le retrouver. C'est le genre de problème qui ne survient pas jusqu'au jour où l'on en constate les symptômes. Et puis une application qui crashe n'est jamais beau à voir ; et une qui perd ses ressources ne fais absolument pas sérieux (surtout si elle doit tourner 24h sur 24).

    La Pile ? Même genre de problème, à la différence que l'on ne peut pas allouer des zones dont on ne connait pas la taille à la compilation, et au détail qu'un échec d'allocation est non rattrapable.

    Comment s'en sortir ? L'idiome RAII est notre ami. Cela signifie envelopper nos ressources dans des objets automatiques comme des smart-pointers ou des vecteurs dans le cas de zones mémoire. Avec ça, je n'ai pas à contrôler chaque allocation de ressource, c'est transparent, à commencer par la désallocation.

    Lecture intéressante :
    - GOTW : items sur l'exception safety
    - Cours C++

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

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 264
    Points : 6 683
    Points
    6 683
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Luc Hermitte
    envelopper nos ressources dans des objets automatiques comme des smart-pointers ou des vecteurs dans le cas de zones mémoire.
    Mais (arêtez-moi de suite si je dis une connerie) c'est pas du tout portable ça non?

  4. #4
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    (arêtez-moi de suite si je dis une connerie)
    Stoooooop !!!

    Les différentes classes de pointeurs intelligents que tu pourras trouver seront toutes portables a priori, puisque c'est un concept qui ne requiert aucun code spécifique au système, on peut tout coder en C++ standard.

    Quant aux vecteurs et autres, ils font partie de la bibliothèque standard, donc la question ne se pose pas.

  5. #5
    Membre habitué
    Inscrit en
    Novembre 2002
    Messages
    120
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 120
    Points : 125
    Points
    125
    Par défaut
    C'est portable! C'est un système d'encapsulation, qu'on peut très bien faire soit même (ici je retire les templates pour faire plus lisible):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class smart_ptr {
       int *p_;
    public:
      smart_ptr() { p = new int; }
      ~smart_ptr() { delete p_; }
      ...
    };

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

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 264
    Points : 6 683
    Points
    6 683
    Billets dans le blog
    2
    Par défaut
    okay désolé

    et donc, si je comprends bien, l'avantage des smart pointers c'est qu'on peut ainsi faire les vérifications necessaires des qu'il y a allocation de mémoire? Ce serait une sorte de factorisation de code: au lieu de vérifier à chaque fois qu'on fait un new machin(), on vérifie dans le new machin(). C'est ça?

  7. #7
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    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 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Non, on ne vérifie rien à ce niveau -- cela sera fait à un niveau qui a du sens par rapport à l'application. Cela sert si une opération échoue après une allocation, la ressource allouée sera alors automatique rendue, vu que l'échec aura détourné le flot de l'exécution (par exception ou retour anticipé).

    Prend du temps et lis le chapitre du C++ in Action. Puis le reste.

    (On ne teste le résultat de new qu'avec les compilos qui ne respectent pas le standard : genre VC 6.x ; ceci dit, il me semble que <new> permet de restorer le comportement standard, qui est de lever une exception)

  8. #8
    Membre habitué

    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 137
    Points : 161
    Points
    161
    Par défaut
    Merci pour vos réponses.

    J'utilise les SmartPtr et les ScopeGuards.
    Mais je les utilise en réponse aux exceptions.
    Je ne les utilise pas en pensant à un problème d'allocation dynamique.

    En gros, si j'ai ce genre de problème, je ne sais pas du tout comment réagira mon programme. Et puis il faudrait faire des try/catch un peu partout et mettre en place un mécanisme de transaction. Ca complique tout. C'est déjà assez difficile de bien gérer toutes les autres exceptions.
    Finalement, est ce que ça en vaut vraiment la peine ?

    C'est le genre de problème qui ne survient pas jusqu'au jour où l'on en constate les symptômes.
    Quels types de symptômes ?

    La Pile ? Même genre de problème, à la différence que l'on ne peut pas allouer des zones dont on ne connait pas la taille à la compilation, et au détail qu'un échec d'allocation est non rattrapable.
    Exactement!
    Donc si on ne peut rien faire au niveau de la pile, c'est un peu de la poudre aux yeux de prendre en compte le tas. (j'en rajoute un peu )

    Sly.

  9. #9
    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
    Citation Envoyé par slylafone
    J'utilise les SmartPtr et les ScopeGuards.
    Mais je les utilise en réponse aux exceptions.
    Je ne les utilise pas en pensant à un problème d'allocation dynamique.
    Sauf que c'est pareil : Quand une allocation dynamique échoue, elle lance une exception... Sauf comme l'a dit Luc avec certains vieux compilos.

  10. #10
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 752
    Points : 10 683
    Points
    10 683
    Billets dans le blog
    3
    Par défaut
    Je crois que ce qu'il se demande c'est comment gérer ça en pratique. Si a chaque fois que tu fais un push_back tu dois mettre ça dans un bloc try...catch tu t'en sors plus.

  11. #11
    Membre habitué

    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 137
    Points : 161
    Points
    161
    Par défaut
    Je crois que ce qu'il se demande c'est comment gérer ça en pratique. Si a chaque fois que tu fais un push_back tu dois mettre ça dans un bloc try...catch tu t'en sors plus.
    Exactement !
    Prenons un cas pratique : Un programme reçoit une liste d'objet qu'il doit insérer dans une base de donnée. Pour garantir l'insertion, on stocke ces objets dans un objet std::queue par exemple avant de tenter de les insérer dans la base de donnée.

    Oui mais std::queue peut déclencher une exception en cas de problème d'allocation dynamique. Donc je ne peux pas vraiment garantir le résultat.
    Dans ce cas, je suppose qu'il n'y aura pas de problème à ce niveau, sinon je ne m'en sort pas!

  12. #12
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    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 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Tu définis donc un scope guard dont le rôle est de faire un rollback (c'est bien donc ça que l'on dit ?) (=> 0 capture à ce niveau) ; et dans un des appelants, tu captureras l'exception pour signaler à l'utilisateur que ce qu'il a voulu faire n'a pas été validé.

    Ce qu'il faut garantir, c'est le côté transactionnel des opérations => si il y a un échec, alors l'état du systême doit demeurer inchangé.

    Pour ce qui est des symptômes, c'est le seul terme qui me venait à l'esprit pour désigner : comportement étrange de l'application et pertes de ressources (fichiers, handles de X ou Y, pots de peintures, mémoire, ...)

  13. #13
    Membre habitué

    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 137
    Points : 161
    Points
    161
    Par défaut
    Ok merci pour la réponse.
    Je comprends bien.

    Mais encore 2 questions :
    - Est ce que ce n'est pas en faire un peu trop, sachant que je n'ai jamais constaté ce type de problème ?
    - Si l'action n'est pas déclenchée par un utilisateur mais par un périphérique, comment je peux faire pour vraiment garantir l'insertion (sachant que je ne peux pas demander au périphérique qu'il me renvoit les données).

  14. #14
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    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 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Tu n'as jamais eu ce problème ... mais si il venait à survenir, tu aurais beaucoup de choses à reprendre.
    Et puis rien ne garanti que le client qui fera tourner l'application le fera dans les meilleures conditions.

    Ensuite, mais qu'est-ce qui est vraiment important à garantir ? L'insertion d'un pour-cent des données ? Leur perte ou la corruption de la base ?

  15. #15
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 752
    Points : 10 683
    Points
    10 683
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par slylafone
    Ok merci pour la réponse.
    Je comprends bien.

    Mais encore 2 questions :
    - Est ce que ce n'est pas en faire un peu trop, sachant que je n'ai jamais constaté ce type de problème ?
    - Si l'action n'est pas déclenchée par un utilisateur mais par un périphérique, comment je peux faire pour vraiment garantir l'insertion (sachant que je ne peux pas demander au périphérique qu'il me renvoit les données).
    1/ Je pense qu'il faut distinguer 2 choses :
    protéger une partie de code qui est sensible à une exception
    gérer les erreurs dans l'ensemble de l'appli.
    Typiquement, si tu te prends un exception tu dois, localement, faire en sorte de ne pas te retrouver dans un état invalide. Par exemple, lors de plusieurs allocation, la dernière échoue, l'exception remonte et tu provoques des fuites de mémoire. Ou le cas de luc : synchronisation entre tes structures en mémoire et une bd, si une est mise à jour et pas l'autre, oups, probleme.
    Soit ta fonction, si son appel échoue par manque de mémoire, il te faut faire en sorte que l'on puisse la rappeler quelques secondes après (une fois la mémoire dispo) pour fonctionner correctement. Ca c'est la gestion locale des erreurs.
    Apres, ta fonction laisse remonter des exceptions et tu t'es ainsi assuré que tu quittes la fontion dans un état cohérent. Au niveau de l'appli il faut maintenant gérer toutes ces exceptions qui peuvent remonter. Plus tu gère ça en amont (par exemple dans la fonction main() ) et plus c'est facile.
    Exemple :
    Tu as 10 fonctions qui font chacune un calcul. Dans ton main tu affiches un menu qui permet d'appeler une fonction au choix. Tu peux mettre ton gestionnaire de bad_alloc dans le main():
    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
    18
    19
     
    int main()
    {
        while ( true )
        {
            AfficheMenu();
            char choix;
            cin >> choix;
            if ( choix == 'q' ) break;
            try
            {
                AppelleFonction( choix );
            }
            catch ( const std::bad_alloc & )
            {
                std::cerr << "Impossible d'effectuer le traitement : mémoire insuffidante\n";
            }
        }
    }
    Dans chaque fonction tu dois t'assurer qu'une exception ne provoque pas des fuites de mémoires, des fichiers non fermés, etc... Mais t'es pas obligé de pourir ton code de try...catch pour autant. Pour peu que tu utilises des objects automatiques, des smart pointers, des scope guards, ton code est exception safe sans avoir un seul bloc try...catch.
    Comme tu vois gérer ces exceptions n'est pas très compliqué, et ça donne une bonne image à ton appli. Il m'arrive de temps en temps, lorsque j'ai la émoire saturée, de lancer des applis en me demandant comment elles vont réagir. Je ne leur en veut pas de se vautrer (quoique si c'est des applis commerciales chères), mais si elles gèrent ça bien c'est très bien perçu.
    Bon cela dit avec une IHM c'est un peu moins évident.

    2/ insertion de quoi ? Comment ça un périph qui déclenche une action ?

  16. #16
    Membre habitué

    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 137
    Points : 161
    Points
    161
    Par défaut
    Merci beaucoup pour cette jolie explication.

    Il m'arrive de temps en temps, lorsque j'ai la émoire saturée, de lancer des applis en me demandant comment elles vont réagir. Je ne leur en veut pas de se vautrer
    Mais dans ce cas, même si la mémoire est saturée, l'OS est capable de faire un swap sur le disque pour libérer de la mémoire, non ?

    Bon cela dit avec une IHM c'est un peu moins évident.
    Cette remarque me fait chaud au coeur. Je trouve aussi.

    Je comprends bien la théorie, et Luc m'avait déjà bien orienté à ce sujet en me présentant les ScopeGuards. Je lui en suis très reconnaissant, car dans la foulé, je me suis mis à m'interessé et à pratiqué ce genre de technique. (i.e. l'idiome RAII).

    Actuellement, je met à jour des anciens programmes (pas de moi) et parrallelement je développe de nouveaux programmes. L'ancien programmeur ne sait jamais soucié de faire des ScopeGuards ou d'utiliser des SmartPtr ni même de gérer les exceptions, et pourtant ses programmes sont réputés très robustes.

    En pratique, protéger une partie de code qui est sensible à une exception ne demande pas forcement du temps (et c'est très bien de le faire), mais faire une bonne gestion des erreurs avec une IHM complexe c'est autre chose je trouve (ça multipli les try/catch). C'est pour ça que je me demande jusqu'où il faut aller... car j'ai déjà pas mal de boulot avec la gestion des erreurs aux accès BD par exemple.

    insertion de quoi ? Comment ça un périph qui déclenche une action ?
    En fait, j'ai un périphérique externe qui envoit des informations sur le port série. Ces informations doivent être affichées et sauvegardées dans la base de données. Mon programme ne doit surtout pas en perdre !

  17. #17
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 752
    Points : 10 683
    Points
    10 683
    Billets dans le blog
    3
    Par défaut
    Mais dans ce cas, même si la mémoire est saturée, l'OS est capable de faire un swap sur le disque pour libérer de la mémoire, non ?
    Mémoire au sens mémoire virtuelle. Le swap aussi peut arriver à satturation... surtout quand il est désactivé comme chez moi

    En fait, j'ai un périphérique externe qui envoit des informations sur le port série. Ces informations doivent être affichées et sauvegardées dans la base de données. Mon programme ne doit surtout pas en perdre !
    Ben si ta BD ne veut plus écrire tu peux pas faire grand chose.

  18. #18
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    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 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Je pense qu'il faut distinguer les types d'erreurs et leurs gravités respectives. Toutes ne se traitent pas de la même façon. Genre la situation extrême où il devient impossible de sauvegarder ce qui arrive sur le flux entrant. Mieux vaut s'arréter proprement que de planter parce que ce cas n'avait pas été envisagé.

    Après, si le moteur est bien découpé de l'IHM, je ne vois pas trop en quoi celle-ci complique plus le traitement des exceptions (si on excepte les risques qu'une exception se produise au niveau IHM alors que l'on en traite déjà une)

    Pour la robustesse, j'ai envie de dire que cela concerne deux choses : les codeurs qui n'introduisent pas de bugs (potentiellement maitrisable), et les situations contre lesquelles on ne peut rien faire (mémoire saturée, disque saturé (ce qui m'arrive de temps à autres) ou défectueux, connection au périphérique rompue, ...)

    (Sinon, je me demandais dans quel enfer on se trouvait quand la mémoire devenait "insuffidante" ... )

  19. #19
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 752
    Points : 10 683
    Points
    10 683
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par Luc Hermitte
    Après, si le moteur est bien découpé de l'IHM, je ne vois pas trop en quoi celle-ci complique plus le traitement des exceptions (si on excepte les risques qu'une exception se produise au niveau IHM alors que l'on en traite déjà une)
    Justement, c'est parce que le moteur est bien découpé que c'est galère. Tu as des dizaines de "connexions" entre le moteur et l'IHM (typiquement le code de gestion d'un clic de bouton appelle une fontion du moteur = une connexion). A chaque connexion il faut un bloc try...catch... T'es facilement tenté de laisser passer le bad_alloc.

  20. #20
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    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 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Ce n'est pas un problème.
    C'est encore un endroit où l'on peut utiliser des macros, ou carrément des fonctions
    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
    18
    19
    template <typename F>
    void run_and_catch(F f)
    {
        std::string message;
        try {
            f();
        } catch(std::bad_alloc &) {
            message = "mémoire insuffisante";
        } catch(my::except_Z &e) {
            message = "problème Z survenu" + e.what();
        } ...
        } catch(std::exception &e) {
            message = "problème: " + e.what();
        }
        App->ErrorBox(message);
    }
     
    ....
        run_and_catch(boost::bind(obj,fn,p1,p2));
    Bon évidemment, cela suppose que pour un type d'exception donné, le message à afficher ne doivent pas trop changer.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Question sur les menus dans les pages HTML non dynamiques (sans PHP, ASP)
    Par o_r_a_x dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 26/05/2009, 16h16
  2. Question sur les vspace + problème commande
    Par Fox213 dans le forum Mise en forme
    Réponses: 6
    Dernier message: 08/10/2008, 21h06
  3. question sur les frames en dynamique
    Par jypees dans le forum Général JavaScript
    Réponses: 0
    Dernier message: 11/12/2007, 14h08
  4. Question sur les bibliothques dynamiques
    Par inh40 dans le forum Autres éditeurs
    Réponses: 1
    Dernier message: 11/04/2007, 15h16
  5. Réponses: 7
    Dernier message: 10/01/2007, 00h37

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