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

Langage Perl Discussion :

Comportement des références différent entre 5.8 et 5.14


Sujet :

Langage Perl

  1. #1
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut Comportement des références différent entre 5.8 et 5.14
    Bonjour la Communauté

    Je viens à vous parce que j'ai un léger soucis dans un script Perl conçu autrefois sous Perl 5.6, qui fonctionne nickel sous Perl 5.8 mais qui plante sous la 5.14.

    L'objectif : migration d'un vieux Linux à un Linux plus récent. Je suis donc en train de tester les comportements de mes programmes personnels et je bloque sur l'un d'eux.

    J'ai un hash de liste tout bête. Chaque clé du hash est bien évidemment unique et contient une liste de 5 valeurs.

    J'alimente ce hash à partir d'un fichier txt contenant par ligne "clé, valeur1, valeur2, ..., valeur 5.

    Mon hash de liste ressemble au final à ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $hash{cle1}[0] = "valeur1";
    $hash{cle1}[1] = "valeur2";
    $hash{cle1}[2] = "valeur3";
    $hash{cle1}[3] = "valeur4";
    $hash{cle1}[4] = "valeur5";
    ... ... ...
    $hash{cle1500}[0] = "valeur1";
    $hash{cle1500}[1] = "valeur2";
    $hash{cle1500}[2] = "valeur3";
    $hash{cle1500}[3] = "valeur4";
    $hash{cle1500}[4] = "valeur5";
    Comme vous le voyez, rien de bien méchant.

    J'ai 6 hash que j'envoie dans une fonction et, bien entendu, j'utilise les références pour bien retrouver mes petits.

    Pour les hash de construction simple (hash{clé}->{valeur}), ça se passe super bien.
    Pour CE hash de liste (hash{clé}->[valeur]), ça fait planter le script lors de l'appel de la fonction.

    L'appel de la fonction se fait comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    TraiteData(\%{$hash_simple1{valeur1}}, \%{$hash_simple2{valeur1}}, 
    \%{$hash_simple3{valeur1}}, \%{$hash_simple4{valeur1}},
     \%{$hash_simple5{valeur1}},
    \%{$hash_de_liste{valeur1}}) # <--- mon hash de liste
    Le début de ma fonction TraiteData :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    sub TraiteData
    {
        my (@hash_simple1, @hash_simple2, @hash_simple3,
     @hash_simple4, @hash_simple5, @hash_de_liste);
     
        (@hash_simple1, @hash_simple2, @hash_simple3, 
    @hash_simple4, @hash_simple5, @hash_de_liste) = @_;
    }
    A l'appel de cette fonction, j'ai droit à un "NOT HASH REFERENCE".

    J'ai isolé les hash un par un et j'ai trouvé que c'était mon hash de liste qui ne passait plus sous Perl 5.14 alors qu'il marche sous 5.8.

    Qu'y a-t-il de mauvais dans ma syntaxe lorsque j'envoie la référence de mon hash de liste à la fonction ?

  2. #2
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    A vrai dire, je suis surpris que ton code fonctionne en 5.8.

    En principe, si tu passes des références (donc des scalaires) à ta fonction, tu dois récupérer des références dans la fonction appelée, pas directement des tableaux.

  3. #3
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    Même remarque que Lolo78, ton code est mal écrit et son fonctionnement sous Perl 5.6 et 5.8 est déjà douteux .

    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
    #!/usr/bin/perl
    use strict;
    use warnings;
     
    my %hash;
    $hash{cle1}[0] = "valeur1";
    $hash{cle1}[1] = "valeur2";
    $hash{cle1}[2] = "valeur3";
    $hash{cle1}[3] = "valeur4";
    $hash{cle1}[4] = "valeur5";
    $hash{cle1500}[0] = "valeur1";
    $hash{cle1500}[1] = "valeur2";
    $hash{cle1500}[2] = "valeur3";
    $hash{cle1500}[3] = "valeur4";
    $hash{cle1500}[4] = "valeur5";
     
    TraiteData($hash{cle1}, $hash{cle1500});
     
    sub TraiteData {
    	my ($ref_tab1, $ref_tab2)= @_;
     
    	foreach my $valeur ( @{$ref_tab1} ) {
    		print "$valeur\n";
    	}
    	print "-----\n";
    	foreach my $valeur ( @{$ref_tab2} ) {
    		print "$valeur\n";
    	}
     
    	return;
    }
    Voici le code clean. À l'appel de la procédure, je passe en argument $hash{cle1}, $hash{cle2}... car les valeurs sont des références de tableaux. Dans la procédure, je récupère ainsi ces dernières.

  4. #4
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Bonsoir Arioch,

    pour en avoir le cœur net, j'ai essayé une version légèrement simplifiée de ton code (deux paramètres passés à la procédure, au lieu de cinq, mais en gardant ta syntaxe), j'ai été limite un peu surpris de voir qu'il compile correctement, mais beaucoup moins surpris de voir qu'il ne marche pas (du moins en 5.10). Je ne vois vraiment pas comment il pouvait marcher en 5.8.

    Après quelques modifications pour utiliser correctement les références, j'obtiens au final un code essentiellement analogue à celui de Djibril à quelques nuances près, et ça marche:

    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
    #!/usr/bin/perl
    use strict;
    use warnings;
     
    my (%hash, %hash_simple1);
    $hash{cle1}[0] = "valeur1";
    $hash{cle1}[1] = "valeur2";
    $hash{cle1}[2] = "valeur3";
    $hash{cle1}[3] = "valeur4";
    $hash{cle1}[4] = "valeur5";
    $hash{cle1500}[0] = "valeur1";
    $hash{cle1500}[1] = "valeur2";
     
    $hash_simple1{"val1"} = "val1";
     
    TraiteData(\$hash_simple1{val1}, $hash{cle1});
     
    sub TraiteData
    {
        my ($hash_simple1_ref, $hash_de_liste_ref) = @_;
        print $$hash_simple1_ref, "\n";
        print "$_\n" foreach @{$hash_de_liste_ref};
    }
    Ce qui imprime:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ perl hash_s.pl
    val1
    valeur1
    valeur2
    valeur3
    valeur4
    valeur5
    Les modifications essentielles sont les suivantes.

    Dans l'appel à la fonction ("TraiteData(\$hash_simple1{val1}, $hash{cle1});"), je passe à la fonction une référence à la valeur contenue dans $hash_simple1{val1} et une référence au tableau contenu dans $hash{cle1}.

    Dans la fonction elle-même, je récupère ces deux valeurs (deux références, donc, deux scalaires), que je déréférence pour imprimer d'abord la valeur contenue dans $hash_simple1{val1}, puis les cinq valeurs contenues dans le tableau pointé par $hash_de_liste_ref, à savoir les cinq valeurs du tableau contenu dans le tableau pointé par $hash{cle1}.

    Remarque: dans le cas des hash simples, passer une référence sur la valeur contenue dans le hash n'a en fait aucun intérêt dans le cas du code ci-dessus se contentant d'imprimer la valeur, un passage par valeur suffisait amplement. Passer une référence au contenu du hash a éventuellement un intérêt si l'on désire modifier le contenu du hash; mais même dans ce cas, un passage par valeur et un retour de la valeur modifiée serait sans doute préférable (code plus lisible et n'utilisant pas des variables globales plus ou moins camouflées, donc, code a priori réentrant). Quelque chose comme cela:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $hash_simple1{"val1"} = "17";
    $hash_simple1{"val1"} = traite_data2( $hash_simple1{"val1"} ); # $hash_simple1{"val1"} vaut maintenant 35
     
    sub traite_data2  {
         my $local_val = shift;
         $local_val ++;
         return 5 * $local_val /2; 
    }
    Bien que, dans ce cas, je ne me fatiguerais même pas à donner une valeur initiale au hash_simple et écrirais plutôt:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    my $var17 = 17;
    $hash_simple1{"val1"} = traite_data2( $var17 ); 
     
    sub traite_data2  {
         my $local_val = shift;
         $local_val ++;
         return 5 * $local_val /2; 
    }
    ou même:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $hash_simple1{"val1"} = traite_data2( 17 ); 
     
    sub traite_data2  {
         # ...
    }

  5. #5
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Merci à vous deux de vous être penchés sur mon cas

    J'ai finalement corrigé mon appel à la fonction comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    TraiteData(\%{$hash_simple1{valeur1}}, \%{$hash_simple2{valeur1}}, 
    \%{$hash_simple3{valeur1}}, \%{$hash_simple4{valeur1}},
     \%{$hash_simple5{valeur1}},
    \@{$hash_de_liste{valeur1}}) # <--- mon hash de liste
    Dans la dernière variable envoyée, j'ai juste remplacé le \% par \@ et ça ne bugge plus.

    Je viens sinon de tester un bout de code similaire sur le Perl 5.8.8 du boulot. Bout de code qui fonctionnait ce week end encore sur le Perl 5.8 de mon ancien Linux. Là, il plante sur la 5.8.8.

    J'ai juste l'impression qu'avant la 5.8.8, le compilateur de Perl était un peu permissif...

    Merci encore !

    Ca m'a permis de refaire un tour ici, comme au bon vieux temps

  6. #6
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    Ta façon de faire n'est toujours pas bonne Arioch. Du moins, elle fonctionnera mais n'est pas bonne.

    Ce code \%{$hash_simple1{valeur1}} est inutile car tu crées la référence d'un hash que tu déréférences. Autant envoyer directement la référence.

    Donc $hash_simple1{valeur1} au lieu de \%{$hash_simple1{valeur1}}

  7. #7
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Oui mais si tu veux, cette partie là du programme fonctionne, aussi ne voudrais-je pas trop y toucher

    En fait, la fonction TraiteData() est une fonction principale qui travaille avec d'autres fonctions dans lesquelles elle passe les mêmes variables.

    Ca me fait changer le code sur beaucoup d'endroits différents.

  8. #8
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    Ok, c'est toi le boss. C'était juste une remarque !

  9. #9
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Pas de soucis djibril, ne prend pas mal ma réponse

    Je comprend ce que tu veux dire, mais j'ai juste mes impératifs derrière.

    Sans oublier que ce programme existe en 3 versions différentes... A l'époque d'ailleurs, si j'avais su j'aurais stocké cette fonction dans un package plutôt qu'en dur dans le script

    Encore merci pour tes réponses et tout pareil pour Lolo78

  10. #10
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Outre les remarques de Lolo et Djibril, que je trouve sensées, je me pose la question suivante concernant cette ligne de la fonction traite_data :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        (@hash_simple1, @hash_simple2, @hash_simple3, 
    @hash_simple4, @hash_simple5, @hash_de_liste) = @_;
    Comment @hash_simple2 à @hash_de_liste peuvent-ils contenir autre que chose que le vide, vu que l'affectation de tableau est gloutonne (tous les éléments de @_ devraient se retrouvés dans @hash_simple1) ???

    Mais comme dit, c'est toi le chef
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  11. #11
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Pas ici, vu que je passe ces tableaux ou hash à la fonction via des références à ces tableaux ou à ces hash.

  12. #12
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ perl -MData::Dumper -E 'sub a { my (@ref1, @ref2) = @_; print Data::Dumper->Dump([\@ref1, \@ref2], [qw(*ref1 *ref2)]) } a([ "toto", "titi" ], { momo => "mimi" })'
    @ref1 = (
              [
                'toto',
                'titi'
              ],
              {
                'momo' => 'mimi'
              }
            );
    @ref2 = ();
    Ou bien quelque chose m'échappe dans ton code.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  13. #13
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Arioch Voir le message
    Pas ici, vu que je passe ces tableaux ou hash à la fonction via des références à ces tableaux ou à ces hash.
    Ben si, toutes les références passées à la fonction vont se retrouver dans le premier tableau et les autres seront vides. Même si je n'ai pas cité explicitement ce point, cela faisait partie des anomalies que j'avais vues et que j'ai corrigées dans le code proposé.

    Bref, si ta fonction marchait vraiment, ce devait être un peu par hasard ou par chance, parce que ce qu'elle fait marchait malgré les anomalies et bien que tu ne manipules pas les données que tu crois manipuler.

  14. #14
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    En fait, mon code étant assez volumineux, j'ai voulu réduire à l'essentiel dans mon exemple.

    Trop apparemment !

    Mais pour les données que ma fonction récupère et qu'elle envoie à de multiples autres fonctions, j'ai pu contrôler le contenu et l'évolution de ces données et c'est OK maintenant.

    Merci à tous pour vos contributions !

Discussions similaires

  1. Comportement des Layout différent en fonction du style utilisé
    Par atha2 dans le forum Composants graphiques
    Réponses: 3
    Dernier message: 17/12/2012, 18h47
  2. [COM] Comportement des références
    Par Sangdrax1604 dans le forum VB.NET
    Réponses: 1
    Dernier message: 17/03/2008, 17h11
  3. Réponses: 12
    Dernier message: 26/10/2007, 16h27
  4. tri des données différent entre 2 bases
    Par j6m dans le forum Oracle
    Réponses: 2
    Dernier message: 12/03/2006, 10h17
  5. Comportement différent entre un bouton et une image
    Par MicheMTP13 dans le forum Général JavaScript
    Réponses: 11
    Dernier message: 07/11/2005, 08h47

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