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

 Delphi Discussion :

Utilité de try finally après le mot-clé New


Sujet :

Delphi

  1. #1
    Membre actif
    Inscrit en
    Décembre 2003
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 491
    Points : 245
    Points
    245
    Par défaut Utilité de try finally après le mot-clé New
    Bonjour,

    J'aimerai clarifier un point avec les records et new.

    Est-ce que l'on doit aussi utiliser un block try ... finally
    avec new

    Merci d'avance

  2. #2
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 490
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 490
    Points : 2 752
    Points
    2 752
    Billets dans le blog
    10
    Par défaut
    NON

  3. #3
    Membre actif
    Inscrit en
    Décembre 2003
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 491
    Points : 245
    Points
    245
    Par défaut
    merci

  4. #4
    Membre expérimenté Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Points : 1 448
    Points
    1 448
    Par défaut
    Ta réponse me parait un peu directive ALWEBER !
    Tout dépend de ce que tu entends pas là. Moi je dirai oui si tu fais une analogie avec le create :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    x := TObject.Create;
    try
      ...
    finally
      x.Free;
    end;
    devient pour un record
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    new(x);
    try
      ...
    finally
      Dispose(x);
    end;
    ... si telle est la question

  5. #5
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 490
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 490
    Points : 2 752
    Points
    2 752
    Billets dans le blog
    10
    Par défaut
    Citation Envoyé par guillemouze Voir le message
    Ta réponse me parait un peu directive ALWEBER !...
    Je prend comme exemple au hasard un élément d'un projet que je migre à partir d'un projet existant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
      RTEditor := TRTEditor.Create(nil);
      try
        RTEditor.Modele := MainManager.Modele;
        RTEditor.LoadFromRT2(f_calcul.GetCalcDir + '/calc.rt2');
        RTEditor.ShowForm(True);
      finally
        FreeAndNil(RTEditor);
      end;
    Cela signifie que le précédent programmeur n'a pas anticipé la mauvaise exécution de sa procédure "LoadFromRT2" qui en fait devrait être une fonction.
    Un code correct devrait avoir plutôt cette forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
      RTEditor := TRTEditor.Create(nil);
      RTEditor.Modele := MainManager.Modele;
      if RTEditor.LoadFromRT2(f_calcul.GetCalcDir + '/calc.rt2') then
        RTEditor.ShowForm(True)
      Else ...
      FreeAndNil(RTEditor);
    Donc c'est une affirmation au regard d'une longue expérience puisque je programme en Pascal et ses descendants depuis 1981.
    Et cette affirmation est vraie sur au moins 80% des cas rencontrés.

  6. #6
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 680
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 680
    Points : 13 086
    Points
    13 086
    Par défaut
    Citation Envoyé par ALWEBER Voir le message
    Et cette affirmation est vraie sur au moins 80% des cas rencontrés.
    Reste 20%. Ce "non" est clairement trop catégorique

    Dans ton exemple, tu considère que f_calcul est assigné. Pourquoi ne pas le tester aussi pour en être sûr ? C'est une source d'erreur potentielle (et que LoadFromRT2 soit une fonction n'y changera rien) à l'instar de ShowForm d'ailleurs...
    Tu pars également du principe que le chemin ne contient pas de "\" terminal, tu le codes en dur. Il serait plus sûr d'utiliser IncludeTrailingPathDelimiter (est-ce une url ?).

    Bref, il y a au moins trois problèmes potentiels dont certains peuvent se révéler critiques. Un try..finally ne serait pas du luxe ici.
    (Pour le "\", c'est surtout l'utilisateur qui ne va pas comprendre pourquoi ce fichier, présent dans le répertoire, ne veut pas se charger...)

    Et la procédure qui va appeler cette procédure devra peut-être également être protégée, TRTEditor.Create pourrait échouer par manque de ressources par exemple. Etc. etc.

    try..finally est la seule façon sûr à 100% de désallouer ce qui l'a été. A ne pas négliger.

  7. #7
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 552
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 552
    Points : 3 918
    Points
    3 918
    Par défaut
    Citation Envoyé par ALWEBER Voir le message
    Je prend comme exemple au hasard un élément d'un projet que je migre à partir d'un projet existant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
      RTEditor := TRTEditor.Create(nil);
      try
        RTEditor.Modele := MainManager.Modele;
        RTEditor.LoadFromRT2(f_calcul.GetCalcDir + '/calc.rt2');
        RTEditor.ShowForm(True);
      finally
        FreeAndNil(RTEditor);
      end;
    Cela signifie que le précédent programmeur n'a pas anticipé la mauvaise exécution de sa procédure "LoadFromRT2" qui en fait devrait être une fonction.
    Un code correct devrait avoir plutôt cette forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
      RTEditor := TRTEditor.Create(nil);
      RTEditor.Modele := MainManager.Modele;
      if RTEditor.LoadFromRT2(f_calcul.GetCalcDir + '/calc.rt2') then
        RTEditor.ShowForm(True)
      Else ...
      FreeAndNil(RTEditor);
    Donc c'est une affirmation au regard d'une longue expérience puisque je programme en Pascal et ses descendants depuis 1981.
    Et cette affirmation est vraie sur au moins 80% des cas rencontrés.
    La mauvaise exécution de LoadFromRT2 provoque visiblement une exception (enfin je l'espère sinon le try...finally n'apporte rien) et transformer cela en fonction qui retourne un code d'erreur est manifestement une incompréhension du principe des exceptions.

    L'anticipation des conditions d'erreur revient à faire de la divination car on ne sait pas a priori comment la procédure LoadFromRT2 va évoluer, avec la gestion d'exception, le code reste relativement sain. Si l'on rajoute de nouvelles conditions d'erreurs dans la procédure, il faut théoriquement revoir le code des appelants pour tenir compte de ces nouvelles erreurs potentielles. Se limiter à un retour booléen (True c'est bon, False c'est mauvais) n'est pas très précis.

    La complexité intrinsèque de la gestion des codes d'erreur de fonction a motivé l'invention de la gestion par exception qui simplifie grandement le code. Transformer une procédure en fonction pour traiter une condition d'erreur est un palliatif à réserver à des langage sans gestion d'exception comme le langage C ou le Turbo Pascal et alors comment traiter les vraies fonctions dont le résultat provient d'un calcul ? Delphi et Free Pascal évitent cet écueil.

    Cdlt

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Citation Envoyé par e-ric Voir le message
    La mauvaise exécution de LoadFromRT2 provoque visiblement une exception (enfin je l'espère sinon le try...finally n'apporte rien) et transformer cela en fonction qui retourne un code d'erreur est manifestement une incompréhension du principe des exceptions.
    Bof, je le vois comme en C++ : faire des exceptions dans des cas rares - exceptionnels, ou pour faire une adaptation d'une bibliothèque ancienne (généralement écrite en C).

    Par exemple, lorsqu'on ne peut pas allouer de la mémoire.


    Citation Envoyé par e-ric Voir le message
    L'anticipation des conditions d'erreur revient à faire de la divination car on ne sait pas a priori comment la procédure LoadFromRT2 va évoluer, avec la gestion d'exception, le code reste relativement sain. Si l'on rajoute de nouvelles conditions d'erreurs dans la procédure, il faut théoriquement revoir le code des appelants pour tenir compte de ces nouvelles erreurs potentielles. Se limiter à un retour booléen (True c'est bon, False c'est mauvais) n'est pas très précis.
    1. Rien n’empêche de retourner un type énuméré
    2. Au lieu de faire un try/ catch qui attrape toutes les exceptions (fourre-tout ), on peut intercepter les exceptions que l'on veut soit 1 par 1 soit par lot. Et on revient au même problème d'évolution qu'avec le retour.


    Lorsque je lis que Andnotor soulève 3 problèmes potentiels, mais en définitive ne fait rien à part passer son chemin


    Citation Envoyé par e-ric Voir le message
    La complexité intrinsèque de la gestion des codes d'erreur de fonction a motivé l'invention de la gestion par exception qui simplifie grandement le code. Transformer une procédure en fonction pour traiter une condition d'erreur est un palliatif à réserver à des langage sans gestion d'exception comme le langage C ou le Turbo Pascal et alors comment traiter les vraies fonctions dont le résultat provient d'un calcul ? Delphi et Free Pascal évitent cet écueil.
    Oui bof Lorsque je vois que la VCL me lance une exception lorsqu'on je donne le focus à un UI qui est caché/ sans parent/ ..., cela m'embête profondément.

    Parce que le problème des exceptions, c'est qu'on ne connait pas toutes les exceptions lancées par une méthode (à moins que la documentation soit bien faite)
    En C++ 03, on peut ajouter à la fin d'une déclaration la liste des exceptions avec le mot clef throw.

    Le retour énuméré a ce petit avantage

  9. #9
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Citation Envoyé par foetus Voir le message
    Bof, je le vois comme en C++ : faire des exceptions dans des cas rares - exceptionnels, ou pour faire une adaptation d'une bibliothèque ancienne (généralement écrite en C).

    Par exemple, lorsqu'on ne peut pas allouer de la mémoire.



    1. Rien n’empêche de retourner un type énuméré
    2. Au lieu de faire un try/ catch qui attrape toutes les exceptions (fourre-tout ), on peut intercepter les exceptions que l'on veut soit 1 par 1 soit par lot. Et on revient au même problème d'évolution qu'avec le retour.


    Lorsque je lis que Andnotor soulève 3 problèmes potentiels, mais en définitive ne fait rien à part passer son chemin
    ne pas confondre try/finally et try/except, le premier permet d'exécuter un code systématiquement, c'est donc tout à fait adapté pour libérer une ressource; le second concerne la gestion des erreurs comme un try/catch

    Citation Envoyé par foetus Voir le message
    Oui bof Lorsque je vois que la VCL me lance une exception lorsqu'on je donne le focus à un UI qui est caché/ sans parent/ ..., cela m'embête profondément.

    Parce que le problème des exceptions, c'est qu'on ne connait pas toutes les exceptions lancées par une méthode (à moins que la documentation soit bien faite)
    En C++ 03, on peut ajouter à la fin d'une déclaration la liste des exceptions avec le mot clef throw.

    Le retour énuméré a ce petit avantage
    le throw est intéressant mais il a ses limites, mais rien n'empêche de filtrer les erreurs selon le type d'exception

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    try
      ...
    except
      on EZeroDivide do HandleZeroDivide;
      on EOverflow do HandleOverflow;
      on EMathError do HandleMathError;
    else
      HandleAllOthers;
    end;
    et même de la propager avec raise.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  10. #10
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 680
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 680
    Points : 13 086
    Points
    13 086
    Par défaut
    1. Try..finally n'est pas un gestionnaire d'exception, juste un bloc inconditionnel ;
    2. il ne s'agit pas de "faire des exceptions" mais de libérer ce qui a été créé/alloué localement, que la procédure se termine normalement, soit interrompue volontairement ou suite à un problème ;
    3. je ne suis pas contre transformer LoadFromRT2 en fonction mais ce n'est pas suffisant ;
    4. à la question "Est-ce que l'on doit aussi utiliser un block try ... finally avec new ?" Ma réponse est oui, par sécurité.


    Citation Envoyé par foetus Voir le message
    Lorsque je lis que Andnotor soulève 3 problèmes potentiels, mais en définitive ne fait rien à part passer son chemin
    Parce que ce n'est pas le sujet mais si je devais proposer quelque chose, ce serait de garder la structure du code originale, quitte à l'améliorer

  11. #11
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 846
    Points
    24 846
    Par défaut
    Vous ne trouvez pas que la question de Marc_3 manque de contexte ?
    D'ailleurs, on ne l'a plus revu dans le coin depuis le NON !
    Il a une réponse totalement incomplète et j'espère qu'il suit cet échange !

    un Exemple ou le try finally n'est pas possible

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure Bidule.Machin();
    var
      pStruct: PStructure;
    begin   
      New(pStruct);
      try
         pStruct^.Champ := Chose();
         ThreadList.Add(pStruct);
      except
         Dispose(pStruct); // Chose ou Add/Grow/SetLength peuvent déclencher une exception
      end;
    end;
    Ensuite la libération est effectué par le TThread qui gère la TThreadList, et cette partie ne garanti pas forcément la libération
    Je l'écrit souvent ainsi ( oui, c'est pas joli joli mais je n'ai pas encore trouvé mieux sans faire une "Usine à gaz" de gestion d'état mais c'est un TOUT AUTRE SUJET)

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
    var
      MoreItem, HaveItem: Boolean;
      Item: TStruture; // ne contient que des types simples et parfois des string
      ItemPtr: PStruture;
      TmpList: TList;
    begin
      try
        if not Terminated then
        begin
          MoreItem := False;
     
          // Parcours de la liste
          repeat
            HaveItem := False;
     
            try
              // Phase 1 - Récupération d'un Elément (on bloque la liste juste le temps qu'il faut)
              TmpList := FThreadList.LockList();
              try
                if TmpList.Count > 0 then
                begin
                  ItemPtr := PFile(TmpList.First());
                  Item := ItemPtr^; // Copie ! 
                  TmpList.Delete(0);
                  Dispose(ItemPtr);
     
                  HaveItem := True;
                  MoreItem := TmpList.Count > 0;
                end
              finally
                FThreadList.UnlockList();
              end;
            except
              on E: Exception do
              begin
                HaveItem := False;
                LogException(E.ClassType(), E.Message); // Ici cela peut être très poussé, entre log fichier, DB, notification par TCP, par mail ... paranoïa absolue !
              end;
            end;
     
            // Phase 2 - Traitement de l'Element !
            if HaveItem then
            begin
              try
                ... Item ...
              except
                on E: Exception do
                  LogException(E.ClassType(), E.Message);
              end;
            end;
          until not MoreItem or Terminated;
        end;
      except
        on E: Exception do
          LogException(E.ClassType(), E.Message);
      end;
    end;
    Vous notez l'absence de finally dans

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
                  ItemPtr := PFile(TmpList.First());
                  Item := ItemPtr^; // Copie ! 
                  TmpList.Delete(0);
                  Dispose(ItemPtr);
    Après tout, la Copie pourrait échouer pour des type string qui impliquerait une allocation à ce moment (j'avoue que je ne maitrise pas le compteur de référence à ce niveau)
    [HS]J'ai appris à gérer le EOutOfMemory à l'époque de D4 sur un PC avec 64 Mo RAM où Win98 passait son temps à utiliser le SWAP
    Cela t'apprend à coder plus léger
    Même Aujourd'hui, à part un logiciel d'imagerie ou d'environnement multi-média (certains gèrent un SWAP interne plus rapide que le SWAP système),
    faut programmer comme un sauvage pour saturer la mémoire d'une machine actuelle[/HS]


    De même le Delete qui appele la méthode redéfinissable Notify pour déclencher une exception

    [HS]J'ai un tas de thread dans ce genre dans module de pilotage de robot ou d'outil supervision ... des programmes qui tournent des semaines échangeant des millions d'évènement entre eux
    Je n'ai jamais eu de problème parce que ces modules n'ont que peu de charge en RAM car fonctionne en flux tendu qui n'arrive jamais à un EOutOfMemory
    C'est ce sujet qui m'a fait remarquer que j'aurais pu mettre un try finally mais si mon programme provoque une exception à ce niveau du code c'est signe d'une défaillance générale
    [/HS]


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
                  ItemPtr := PFile(TmpList.First());
                  try
                    Item := ItemPtr^; // Copie ! 
                    TmpList.Delete(0);
                  finally
                    Dispose(ItemPtr)
                  end;


    Un autre cas ou le try finally semble logique



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure Bidule.Machin();
    var
      pStruct: PStructure;
    begin   
      New(pStruct);
      try
         Chose(pStruct);
      finally
         Dispose(pStruct);
      end;
    end;
    mais c'est un code bien lourd pour un pointeur locale dont la durée de vie reste interne à la fonction donc on peut écrire simplement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure Bidule.Machin();
    var
      Struct: TStructure;
    begin   
      Chose(@Struct);
    end;

    "Doit-on Utiliser try .. finally après un New ?" n'est pas la bonne question !
    Pour moi, la bonne question est "A quel moment utliser un New ?"

    et même si NON d'ALWEBER me choque par son absence d'argumentation, il n'est pas totalement faux !

    le try .. finally pour avoir un code propre qui gère bien la mémoire est une évidence
    Mais alloué dynamiquement ce qui n'a pas besoin de l'être complexifie inutilement un code
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  12. #12
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 680
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 680
    Points : 13 086
    Points
    13 086
    Par défaut
    Si on envisage un try..finally après New/Create, c'est logiquement que sa portée est locale.

    @Shai : MoreItem n'étant pas initialisé, tu risques la boucle sans fin

  13. #13
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 846
    Points
    24 846
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Si on envisage un try..finally après New/Create, c'est logiquement que sa portée est locale.
    Si l'on est en portée locale
    Pour un objet via Create c'est logique car indispensable puisque de Delphi ne gère que des objets par référence contrairement au C++ où l'on peut faire un objet en allocation statique ou un objet en allocation dynamique
    Pour un pointeur géré par GetMem/FreeMem parce que l'on ne peut pas déterminer la taille du buffer en DesignTime le "try .. finally" prend tout son sens
    Pour un pointeur géré par New qui si me trompe pas ne fonctionne que sur pointeur typé qui détermine la taille à allouer (sur Pointer cela renvoie nil), c'est donc je pense totalement inutile puisque l'opérateur @ peut faire le travail


    [HS]
    Citation Envoyé par Andnotor Voir le message
    @Shai : MoreItem n'étant pas initialisé, tu risques la boucle sans fin .
    Chipoteur, tu ne l'as pas vu dans les "..."
    c'est ça de copier partiellement un code, bon c'est corrigé par pure cohérence de cet HS
    Comme je n'ai AUCUN warning dans ces modules, j'aurais tout de suite vu un "warning W1036: W1036 La variable 'MoreItem' n'a pas été initialisée"
    [/HS]
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  14. #14
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 680
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 680
    Points : 13 086
    Points
    13 086
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Chipoteur, tu ne l'as pas vu dans les "..."
    c'est ça de copier partiellement un code, bon c'est corrigé par pure cohérence de cet HS
    Comme je n'ai AUCUN warning dans ces modules, j'aurais tout de suite vu un "warning W1036: W1036 La variable 'MoreItem' n'a pas été initialisée"
    Je suis taquin

    Je me doutais qu'il y en avait un, mais sans vouloir chipoter plus, il n'est pas à la bonne place ! Si TmpList contient plusieurs éléments et que l'erreur survient sur le deuxième (ou suivants), MoreItem est vrai ad vitam aeternam.

  15. #15
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Pour un pointeur géré par New qui si me trompe pas ne fonctionne que sur pointeur typé qui détermine la taille à allouer (sur Pointer cela renvoie nil), c'est donc je pense totalement inutile puisque l'opérateur @ peut faire le travail
    pas forcément, si tu utilises un Record statique, il est placé sur la Pile, alors que New alloue sur le Tas. Un cas simple ou cela pose problème est celui d'une méthode récursive, avec un Record un peu gros sur la pile tu exploses rapidement la pile, avec un New ça n'arriverais que beaucoup plus tard car tu n'utilises qu'un pointeur dans la pile.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  16. #16
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 846
    Points
    24 846
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    pas forcément, si tu utilises un Record statique, il est placé sur la Pile, alors que New alloue sur le Tas. Un cas simple ou cela pose problème est celui d'une méthode récursive, avec un Record un peu gros sur la pile tu exploses rapidement la pile, avec un New ça n'arriverais que beaucoup plus tard car tu n'utilises qu'un pointeur dans la pile.
    J'allais éditer mon message pour évoquer une structure pointant sur un très gros tableau comme dans ce sujet mais la récursivité est aussi un cas tout à fait intéressant au quel je n'avais pas songé !

    Comme quoi, le contexte est bien très important pour bien répondre à la question !
    J'espère que Marc_3 va nous lire, car c'est plutôt le OUI qui l'emporte sur le NON


    [HS]
    Citation Envoyé par Andnotor Voir le message
    Je me doutais qu'il y en avait un, mais sans vouloir chipoter plus, il n'est pas à la bonne place ! Si TmpList contient plusieurs éléments et que l'erreur survient sur le deuxième (ou suivants), MoreItem est vrai ad vitam aeternam
    tout à fait, j'en ai déjà corrigé dans ce sens en passant MoreItem/HaveItem à False au début du repeat et/ou dans le except
    Je vois qu'il m'en reste encore !
    [HS]
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 09/10/2008, 21h35
  2. Cadre contenant les mots cles les plus recherchés
    Par jibs79 dans le forum Référencement
    Réponses: 4
    Dernier message: 04/04/2007, 11h17
  3. [VB6] erreur de compilation:utilisation incorrecte du mot clé New
    Par fouf_01 dans le forum VB 6 et antérieur
    Réponses: 16
    Dernier message: 17/05/2006, 16h22

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