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 :

Allocation dynamique d'un tableau bidimensionnel par fonction


Sujet :

C

  1. #1
    Membre régulier Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Points : 95
    Points
    95
    Par défaut Allocation dynamique d'un tableau bidimensionnel par fonction
    Bonjour,

    J'aimerais vérifier l'intégrité d'un fichier en ajoutant un message d'erreur à un log, qui n'est autre qu'un tableau de chaînes de caractères en (char **), à chaque fois qu'une anomalie est détectée. J'ai donc créé une fonction qui ajoute un message d'erreur contenu dans une table (de type tableau statique de chaînes statiques de caractères) à ce log, avec les coordonnées de l'anomalie (i_module ; i_error).

    Cependant, j'ai une segfault dès que je touche à mon pointeur à travers un nouveau pointeur... Je dois pas avoir les yeux en face des trous, mais ça fait quand même pas mal de temps que je debug sans résultats : pourriez-vous m'aider, je vous prie ?
    Voici la fameuse fonction :
    Code C : 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
    static void add_error_msg(bool offers, size_t *n_errors, size_t i_module, size_t i_error, char ***out)
    {
       *out = NULL; 
       *out = realloc(*out, (++(*n_errors)) * sizeof **out);
       if(*out != NULL) {
          char *temp = (*out)[*n_errors - 1];
          if((temp = malloc((strlen("Module XXXX : ") + 1 + strlen(error_table[i_error])) * sizeof *temp)) != NULL)
             sprintf(temp, "Module %u%c : %s", i_module, offers ? 'o' : 'e', error_table[i_error]);
          else
             fprintf(stderr, "Impossible d'allouer un message d'erreur");
       }
       else fprintf(stderr, "Impossible d'allouer le log d'erreur");
    }
     
    /* ------------------------------------------------------------------------
       Utilisation : */
     
    char **log = NULL;
    size_t n_errors = 0;
     
    add_error_msg(true, &n_errors, 0, 0, &log); // Par exemple

    Merci d'avance.

  2. #2
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par kidpaddle2 Voir le message
    Bonjour,

    J'aimerais vérifier l'intégrité d'un fichier en ajoutant un message d'erreur à un log, qui n'est autre qu'un tableau de chaînes de caractères en (char **), à chaque fois qu'une anomalie est détectée. J'ai donc créé une fonction qui ajoute un message d'erreur contenu dans une table (de type tableau statique de chaînes statiques de caractères) à ce log, avec les coordonnées de l'anomalie (i_module ; i_error).

    Cependant, j'ai une segfault dès que je touche à mon pointeur à travers un nouveau pointeur... Je dois pas avoir les yeux en face des trous, mais ça fait quand même pas mal de temps que je debug sans résultats : pourriez-vous m'aider, je vous prie ?
    Voici la fameuse fonction :
    Code C : 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
    static void add_error_msg(bool offers, size_t *n_errors, size_t i_module, size_t i_error, char ***out)
    {
       *out = NULL; 
       *out = realloc(*out, (++(*n_errors)) * sizeof **out);
       if(*out != NULL) {
          char *temp = (*out)[*n_errors - 1];
          if((temp = malloc((strlen("Module XXXX : ") + 1 + strlen(error_table[i_error])) * sizeof *temp)) != NULL)
             sprintf(temp, "Module %u%c : %s", i_module, offers ? 'o' : 'e', error_table[i_error]);
          else
             fprintf(stderr, "Impossible d'allouer un message d'erreur");
       }
       else fprintf(stderr, "Impossible d'allouer le log d'erreur");
    }
     
    /* ------------------------------------------------------------------------
       Utilisation : */
     
    char **log = NULL;
    size_t n_errors = 0;
     
    add_error_msg(true, &n_errors, 0, 0, &log); // Par exemple

    Merci d'avance.
    Tu fais un peu n'importe quoi dans ta fonction... Il faut faire les choses dans le bon ordre :
    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
     
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
     
    typedef enum
    { false, true }
    bool;
     
    static char const *error_table[] = {
       "a",
       "bb",
       "cc c",
       "dd dd",
    };
     
    static void add_error_msg (bool offers, size_t * n_errors, size_t i_module,
                               size_t i_error, char ***out)
    {
       *out = realloc (*out, (++(*n_errors)) * sizeof **out);
       if (*out != NULL)
       {
          char *temp = malloc ((strlen ("Module XXXX : ") + 1 +
                                strlen (error_table[i_error])) * sizeof *temp);
          if (temp != NULL)
          {
             sprintf (temp, "Module %u%c : %s", i_module, offers ? 'o' : 'e',
                      error_table[i_error]);
             (*out)[*n_errors - 1] = temp;
          }
          else
             fprintf (stderr, "Impossible d'allouer un message d'erreur");
       }
       else
          fprintf (stderr, "Impossible d'allouer le log d'erreur");
    }
     
    /* ------------------------------------------------------------------------
       Utilisation : */
    int main (void)
    {
       char **log = NULL;
       size_t n_errors = 0;
     
    /* Par exemple */
       add_error_msg (true, &n_errors, 0, 0, &log);
       add_error_msg (true, &n_errors, 0, 2, &log);
       add_error_msg (true, &n_errors, 0, 1, &log);
     
       {
          size_t i;
          for (i = 0; i < n_errors; i++)
          {
             printf ("'%s'\n", log[i]);
          }
       }
       return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    'Module 0o : a'
    'Module 0o : cc c'
    'Module 0o : bb'
     
    Process returned 0 (0x0)   execution time : 0.018 s
    Press any key to continue.
    Mais on est loin d'être sécurisé, et le codage est trop complexe pour être fiable...

    Je propose une organisation plus rationnelle :
    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
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
     
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
     
    typedef enum
    { false, true }
    bool;
     
    static char const *error_table[] = {
       "a",
       "bb",
       "cc c",
       "dd dd",
    };
     
    struct log
    {
       char **tab;
       size_t n;
    };
     
    static void log_init (struct log *this)
    {
       this->n = 0;
       this->tab = NULL;
    }
     
    static void log_add_error_msg (struct log *this, bool offers, size_t i_module,
                                   size_t i_error)
    {
       void *tmp = realloc (this->tab, (this->n + 1) * sizeof *this->tab);
       if (tmp != NULL)
       {
          this->tab = tmp;
     
          {
             size_t const len =
                strlen ("Module XXXX : ") + 1 + strlen (error_table[i_error]);
             char *s = malloc (len * sizeof *s);
             if (s != NULL)
             {
                sprintf (s, "Module %u%c : %s", i_module, offers ? 'o' : 'e',
                         error_table[i_error]);
                this->tab[this->n] = s;
             }
             else
             {
                fprintf (stderr, "Impossible d'allouer un message d'erreur");
                this->tab[this->n] = NULL;
             }
             this->n++;
          }
       }
       else
       {
          fprintf (stderr, "Impossible d'allouer le log d'erreur");
       }
    }
     
    static void log_print (struct log const *this)
    {
       size_t i;
       for (i = 0; i < this->n; i++)
       {
          printf ("'%s'\n", this->tab[i]);
       }
    }
     
    /* ------------------------------------------------------------------------
       Utilisation : */
    int main (void)
    {
       struct log log;
     
       log_init (&log);
     
       log_add_error_msg (&log, true, 0, 0);
       log_add_error_msg (&log, true, 1, 2);
       log_add_error_msg (&log, true, 0, 1);
     
       log_print (&log);
     
       return 0;
    }

  3. #3
    Membre régulier Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Points : 95
    Points
    95
    Par défaut
    Ton premier code ne changeait pas grand-chose (ce n'est qu'une restructuration), mais j'ai finalement découvert en rajoutant un test sur "out" tout court, qu'en oubliant une étoile dans la fonction appelante je lui envoyais toujours NULL

    Donc c'est réglé, ça marche et je te remercie de m'avoir proposé quelque chose de plus fonctionnel, ça fait toujours plaisir de profiter de ton expérience (d'autant plus que c'est une initiative personnelle pour mon école, donc le plus stable le bébé sera, le plus tranquille je serai ).

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par kidpaddle2 Voir le message
    Ton premier code ne changeait pas grand-chose (ce n'est qu'une restructuration),
    Tu rigoles ?
    est faux, la gestion de l'index était fausse etc. Ton code, je l'ai corrigé.

Discussions similaires

  1. [debutant] allocation dynamique d'un tableau.
    Par méphistopheles dans le forum Débuter
    Réponses: 3
    Dernier message: 16/03/2007, 12h45
  2. Réponses: 2
    Dernier message: 05/03/2007, 18h37
  3. Réponses: 67
    Dernier message: 13/02/2007, 18h08
  4. Réponses: 13
    Dernier message: 01/10/2006, 00h25
  5. [PRO*C] Allocation dynamique d'un tableau de VARCHAR
    Par NéalZheimer dans le forum Interfaces de programmation
    Réponses: 5
    Dernier message: 07/07/2006, 13h02

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