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 :

variable modifiée après appel de procédure


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2005
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 31
    Par défaut variable modifiée après appel de procédure
    Bonjour,

    J'ai écrit une procédure prenant en paramètre un pointeur vers une matrice creuse (qui est une structure à 4 champs : nombre de lignes/colonnes et deux pointeurs lignes/colonnes vers un tableau de pointeurs, voir schéma) et qui affiche les éléments (non nuls du coup) en parcourant les listes du tableau lignes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void affiche_creuse(struct creuse_t * ptr_matrice){
      int i ;
      struct cell_t * p ; // pointeur courant
      p = malloc(sizeof(struct cell_t)) ;
     
      for(i=0 ; i<ptr_matrice->nbr_lig ; i++){
        p = *((ptr_matrice->lignes)+i) ; // pointe sur la première cellule de la ligne i
        while (p != NULL){ // affiche des cellules de la ligne i
          printf("%5i",p->val);
          p = p->suiv_lig ;
        }
        printf("\n");
      }
    }
    Le problème c'est qu'une fois dans cette procédure (avec comme paramètre ptr_creuse qui pointe vers une matrice creuse précédemment initialisée) la matrice *(ptr_creuse) change! Et ceci dès qu'on alloue de la mémoire pour le pointeur courant p, est-ce qu'il pourrait "écraser" de la mémoire où était écrite la matrice *(ptr_creuse) ? Pourtant dans le main j'ai pris soin d'allouer de la mémoire pour ce pointeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    struct creuse_t * ptr_creuse ;
    ptr_creuse = malloc(sizeof(struct creuse_t)) ;
    Voici une capture d'écran décrivant ce qui se passe avec gdb : capture

    Merci !

  2. #2
    Membre émérite
    Avatar de Elijha
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Avril 2003
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Avril 2003
    Messages : 314
    Par défaut
    Bonsoir,

    Pourquoi allouer de la mémoire sur ton pointeur P ? En plus en sortie de ta procédure, tu ne le désalloue pas free(p).
    Avec struct cell_t * p = ptr_matrice cela devrait suffire. Et si tu ne veux pas que ptr_matrice soit modifié, déclare le en const.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void affiche_creuse(const struct creuse_t * ptr_matrice)

  3. #3
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Pourtant dans le main j'ai pris soin d'allouer de la mémoire pour ce pointeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    struct creuse_t * ptr_creuse ;
    ptr_creuse = malloc(sizeof(struct creuse_t)) ;
    Cette remarque associée à ce code et en considérant également cette allocation inutile ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      struct cell_t * p ; // pointeur courant
      p = malloc(sizeof(struct cell_t))
    semble montrer une confusion : L'allocation du pointeur est réalisée par sa définition " type * pointeur ; ". Il n'est pas obligatoire de faire derrière un malloc(). La seule obligation est de mettre une adresse valide avant de s'en servir. Dans le deuxième code une valeur sera donnée en temps utile à ce pointeur par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      p = *((ptr_matrice->lignes)+i) ;
    qui est une manière compliquée d'écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      p = ptr_matrice->lignes[i];
    Par contre, tu ne montres pas du tout comment est initialisée la structure (allouée dynamiquement) qui est pointée par ptr_creuse ni la construction de la matrice creuse. On n'a pas d'informations suffisantes pour établir un diagnostic.

    Il faut donner :
    1- la définition de struct creuse_t et struct cell_t
    2- un code montrant la construction d'une matrice creuse et permettant de reproduire le problème.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Février 2005
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 31
    Par défaut
    Bonjour,

    Effectivement ça ne sert à rien d'allouer de la mémoire pour le pointeur p.

    Voici la structure de données :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // le type cellule
    struct cell_t {
        int val; // valeur de la cellule
        unsigned lig, col; // position de la cellule dans la matrice
        struct cell_t *suiv_lig, *suiv_col; // liens vers les cellules voisines
    };
     
    // le type matrice creuse
    struct creuse_t {
        unsigned nbr_lig; // le nombre de lignes de la matrice
        struct cell_t **lignes; // tableau des lignes
        unsigned nbr_col; // le nombre de lignes de la matrice
        struct cell_t **colonnes; // tableau des colonnes
    };
    La fonction qui construit la matrice creuse fonctionne très bien (elle implémente le schéma de mon premier message), ce qui ne va pas c'est lorsque je passe en paramètre le pointeur vers cette matrice à la fonction d'affichage (alors que si je passe la matrice directement ça marche).

    Regardez la matrice pointée par ptr_creuse change dès que p passe au suiv ! ici

    Merci !

  5. #5
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Je continue à suspecter la construction ou la manière d'utiliser la matrice *ptr_mat en argument parce que je ne remarque pas d'anomalies flagrantes dans le code de cette fonction (on ne peut pas tester, c'est trop long de construire un code compilable complet).
    Je persiste :
    Il faut donner :
    ....
    2- un code montrant la construction d'une matrice creuse et permettant de reproduire le problème.
    On gagnera du temps en éliminant des sources éventuelles de problèmes et on pourra tester.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Février 2005
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 31
    Par défaut
    Ok, je suis curieux de savoir où est le bug, voici le code minimal pour lequel ça plante :

    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
    #include <time.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    // Fonctions de manipulation de matrices pleines
     
    // definition de constantes globales
    #define L 7 // Largeur de la matrice pleine
    #define H 4 // Hauteur de la matrice pleine
     
    // initialise une matrice pleine avec des entiers aleatoires
    void init_pleine(int pleine[H][L])
    {
        // initialisation du generateur de nombres aleatoires
        srand(time(NULL));
        for (unsigned l = 0; l < H; l++) {
            for (unsigned c = 0; c < L; c++) {
                // une facon de garantir qu'il y aura beaucoup de 0
                pleine[l][c] = (rand() % 19) - 9;
                if (pleine[l][c] % 2 == 0) pleine[l][c] = 0;
            }
        }
    }
     
    // affiche une matrice pleine
    void affiche_pleine(int pleine[H][L])
    {
        for (unsigned l = 0; l < H; l++) {
            for (unsigned c = 0; c < L; c++) {
                printf("%5d ", pleine[l][c]);
            }
            printf("\n");
        }
        printf("\n");
    }
     
    // Fonctions de manipulation de matrices creuses
     
    // le type cellule
    struct cell_t {
        int val; // valeur de la cellule
        unsigned lig, col; // position de la cellule dans la matrice
        struct cell_t *suiv_lig, *suiv_col; // liens vers les cellules voisines
    };
     
    // le type matrice creuse
    struct creuse_t {
        unsigned nbr_lig; // le nombre de lignes de la matrice
        struct cell_t **lignes; // tableau des lignes
        unsigned nbr_col; // le nombre de lignes de la matrice
        struct cell_t **colonnes; // tableau des colonnes
    };
    Merci.

  7. #7
    Membre expérimenté Avatar de quetzacoatl
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 168
    Par défaut
    Tu fais:
    cell->suiv_lig = *(tab_lignes+i) ; // tab_lignes[i] ;
    cell->suiv_col = *(tab_colonnes+j) ;
    Alors pourquoi as tu mis en commentaire tes réservations de mémoire?:
    struct cell_t ** tab_lignes ;
    // tab_lignes = calloc(H,sizeof(struct cell_t *)) ;
    struct cell_t ** tab_colonnes ;
    // tab_colonnes = calloc(L,sizeof(struct cell_t *)) ;
    Ces réservations mémoire sont essentielles au code

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Février 2005
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 31
    Par défaut
    Merci beaucoup ! Je ne me referai plus jamais avoir !

    Désolé les trucs en commentaires c'était un essai j'ai oublié de décommenter ensuite.

    Bonne soirée !

Discussions similaires

  1. [Débutant] Récuperer une variable modifier après un "if"
    Par FruitSellers dans le forum C#
    Réponses: 1
    Dernier message: 29/01/2014, 16h31
  2. Réponses: 2
    Dernier message: 25/08/2009, 16h46
  3. Réponses: 26
    Dernier message: 24/06/2009, 09h32
  4. récupérer une variable après appel asynchrone à une jsp
    Par troussepoil dans le forum Servlets/JSP
    Réponses: 9
    Dernier message: 29/08/2008, 14h07
  5. Appel de procédure par contenu de variable
    Par lil_jam63 dans le forum Langage
    Réponses: 9
    Dernier message: 13/09/2004, 08h05

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