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 :

[langage] Comportement étrange d'une variable


Sujet :

Langage Perl

  1. #1
    Candidat au Club
    Inscrit en
    Avril 2004
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 5
    Points : 4
    Points
    4
    Par défaut [langage] Comportement étrange d'une variable
    Bonjour,

    Je me trouve face à un problème qui parait anodin mais qui m'embête profondément, et surtout qui frise le surnaturel

    Explication :

    J'utilise plusieurs listes dans mon scripts et j'effectue divers traitement dessus. Je rencontre le problème suivant : lorsque j'écris dans un emplacement sur une liste, ça écris la même chose au même endroit dans l'autre liste!

    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $liste1[0][1] = "texte1";
    $liste2[0][1] = "texte2";
    Si je fais la chose suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $liste2[0][1] = "coucou";
    print $liste1[0][1]; # Affiche coucou !!!!
    Voilà, il faut savoir que c'est dans un script PERL de plus de 200 lignes qui consomme pas mal de ressources. J'utilise la module USE STRICT.

    On dirait qu'il y a un pointeur ou une liaison entre les listes c'est vraiment très étrange, si quelqu'un a déjà vu rencontré ce type de problème...

    Merci.

  2. #2
    En attente de confirmation mail
    Inscrit en
    Mars 2002
    Messages
    67
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 67
    Points : 75
    Points
    75
    Par défaut
    et si tu fais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $$liste1[0][1] = "texte1";
    $$liste2[0][1] = "texte2";
     
    $$liste2[0][1] = "coucou";
    print $$liste1[0][1];

  3. #3
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Ce problème ne frise pas le surnaturel, il est probablement dû à une ligne antérieure, où tu as affecté le même tableau au sous-tableau de ces deux listes, par conséquent, ces deux listes (ou du moins leur sous tableau n°0) se réfèrent au même tableau en mémoire, d'où le problème...
    C'est un cas assez fréquemment rencontré dans les langages de haut niveau, quand ils autorisent à manipuler des références ou autres qui s'assimilent à des pointeurs, à cause de leur nature de haut niveau et de leur permissivité, les programmeurs ont tendance à oublier tous ces problèmes de pointeur et de mémoire et à faire des assignation comme ça, sans réfléchir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    @liste1[0] = \@liste_de_base;
    @liste2[0] = \@liste_de_base;
    Donc il suffit que tu retrouves ces assignations, et que tu les remplaces par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    @liste1[0] = [@liste_de_base];
    @liste2[0] = [@liste_de_base];
    Mais il est également possible que le problème soit plus vicieux, par exemple une assignation dans une boucle alors que le tableau a été initialisé à l'extérieur. Pour un exemple de ce cas, un post récent en présente plusieurs facettes.

    --
    Jedaï

  4. #4
    Candidat au Club
    Inscrit en
    Avril 2004
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 5
    Points : 4
    Points
    4
    Par défaut
    Bonjour et merci de vous intéresser à mon problème.

    Pour commencer, lors que je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $$liste1[0][1] = "texte1"; 
    $$liste2[0][1] = "texte2"; 
     
    $$liste2[0][1] = "coucou"; 
    print $$liste1[0][1];
    Cela me produit une erreur, comme quoi je n'ai pas déclaré $liste2. D'après ce que j'ai pu lire après quelque recherche, $$ est un scalaire prédéfinies qui contient l'ID de processus du processus actuel, dans lequel tourne le script, tel qu'il a été affecté par le système d'exploitation.

    Pour entrer un peu plus dans les détails, voilà la démarche de mon programme :

    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
     
    # Déclaration des listes
    my @result1;
    my @result2;
    my @result3;
     
    # Traitement et remplissage de @result1
    ...
     
    # Traitement sur @result1 et remplissage de @result2
    ...
     
    # Traitement sur @result2 et remplissage de @result3
    .... #Traitement
    @result2 = @result3; #Copie du contenu de @result2 dans @result3
    @result3 = undef;
     
    # Traitement sur @result2 et remplissage de @result3
    ... # Traitement
    @result2 = @result3; # Ici j'ai la même chose dans les 2 listes 
     
    # Traitement sur @result3 SEULEMENT
    for ($m=0;$m<$var;$m++) {
          $result3[$m][2] = "coucou"; # [color=red]*[/color]
          ...
    }
    * C'est ici mon problème, cette ligne a pour effet d'écrire aussi dans $result2[$m][2].

    J'ai essayé lors de mes copies de listes les choses suivantes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    @result2 = (@result3);
    @result2 = [@result3];
    @result2 = \@result3;
    Cela a pour effet de bloquer mon script CGI, le traitement s'arrête et je n'ai plus aucun affichage à l'écran.
    Je n'ai jamais eu ce problème auparavant alors que je copiais des listes dans d'autres listes sans problèmes.

  5. #5
    Candidat au Club
    Inscrit en
    Avril 2004
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 5
    Points : 4
    Points
    4
    Par défaut
    J'ai trouvé une solution provisoire, réaffecter les colonnes des listes 1 par 1, à savoir qu'au lieu de faire ça :

    Je fais la chose suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for ($m=0;$m<@result3;$m++) {
         $result2[$m][0] = $result3[$m][1];
         $result2[$m][1] = $result3[$m][2];
         $result2[$m][2] = $result3[$m][3];
    }
    Mais bon le mystère reste entier...

  6. #6
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    C'est là qu'est le problème : avec des listes normales ça marche parce que toutes les valeurs de @result3 sont copiées dans @result2, mais réfléchit bien, qu'y a-t-il dans @result3 dans ce cas particulier ?? Des références vers des sous-tableau, ces références sont donc copiées d'un tableau dans l'autres, mais elles continuent à pointer sur les mêmes sous tableaux...

    Le problème est donc clair, et dans ce cas particulier (tableau de tableaux), facilement réglable, il suffit de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    for my $i (0..$#result3) {
        $result2[$i] = [ @{ $result3[$i] } ]
    }
    qui est un peu plus rapide que ta solution, et un peu plus généraliste.

    Néanmoins, pour être vraiment général, il existe un module de la distribution standard qui permet d'effectuer une "vraie" copie, sans en passer par la phase de réflexion :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    use Storable qw(dclone);
     
    @result2 = @{ dclone(\@result3)  };
    Là, on est sûr du résultat, quelle que soit la structure interne de @result3 (évidemment, s'il s'agit d'une simple liste, c'est un peu dispendieux, mais bon...).

    --
    Jedaï

  7. #7
    Candidat au Club
    Inscrit en
    Avril 2004
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 5
    Points : 4
    Points
    4
    Par défaut
    Merci beaucoup pour ces précisions Jedai, cela pourra servir à d'autres personnes qui pourraient se retrouver confronté à ce genre de problème.

    Je prends notes des autres méthodes de clonage de liste qui semble plus légère et surtout plus efficace, et comme j'ai besoin d'économiser les ressources au maximum cela convient parfaitement.

    Au plaisir, ++

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

Discussions similaires

  1. [langage] probleme sur test d'une variable
    Par Melvine dans le forum Langage
    Réponses: 11
    Dernier message: 25/10/2006, 19h31
  2. [langage] trouver une variable dans une autre
    Par BEAUJAULT dans le forum Langage
    Réponses: 2
    Dernier message: 19/08/2004, 15h04
  3. Réponses: 6
    Dernier message: 08/06/2004, 14h22
  4. Réponses: 2
    Dernier message: 23/03/2004, 11h24
  5. [langage] Extraire un block dans une variable multiligne
    Par |DUCATI| DesMo dans le forum Langage
    Réponses: 9
    Dernier message: 11/02/2003, 14h56

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