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 :

Trouvez une erreur de conception dans un code


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2006
    Messages
    27
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2006
    Messages : 27
    Points : 23
    Points
    23
    Par défaut Trouvez une erreur de conception dans un code
    Voici une des questions de l'ancien exam de C de ma faq. Personne a trouvé le resultat et j'en ai marre de chercher sur google. Donc j'ai pensé à vous.

    Trouvez l'erreur de conception du code suivant.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    typedef struct _A A;
    struct _A{
       va_list ap;
    };
     
    A* A_new(va_list ap)
    {
       A* a=malloc(sizeof(*a));
       if(a)a->ap=ap;
       return a;
    }

  2. #2
    Membre averti Avatar de Bob.Killer
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    336
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 336
    Points : 332
    Points
    332
    Par défaut
    le soucis c'est qu'on ne crée pas une variable pour chacune des cellules A, mais on recopie simplement le pointeur de la cellule passé en paramêtre.

    va_list équivaut à char*

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    A* a=malloc(sizeof(*a));
    if(a)
      a->ap=ap;
    ce bloque crée une nouvelle cellule, mais prend le même pointeur que la cellule passé en paramêtre pour le 'ap', ce qu'il ne doit pas nous intéressé je suppose...
    il faudrait créer un nouvel espace mémoire pour stocker la chaine voulu.

    enfin c'est un peu tarabiscoté comme programme lol

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    Bonjour,

    Merci de votre réponse.
    Si je comprends bien, il faudrait rajouter:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    if(a)
    {
          a->ap=malloc(sizeof(*ap));
          a->ap=ap;
    }
    Merci de vos éclairages sur ce problème

  4. #4
    Membre du Club
    Inscrit en
    Avril 2007
    Messages
    40
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 40
    Points : 46
    Points
    46
    Par défaut
    C'est presque ça .... sauf que tu perds la zone mémoire si tu fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    if(a)
    {
          a->ap=malloc(sizeof(*ap));
          a->ap=ap;
    }
    Le plus approprié serait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    if(a)
    {
          a->ap=malloc(sizeof(*ap));
          strcpy(a->ap,ap);
    }
    Tu recopies chaque caractère dans le nouvel espace alloué, mais ton allocation mémoire ne correspond pas non plus

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    a->ap = malloc( sizeof(char)*(strlen(ap)+1) ); // +1 pour le caractère \0
    Ton malloc va allouer 1 char.

  5. #5
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    - Le problème n'est pas là et n'a rien à voir avec les cellules (listes chaînées ?) ou les chaînes de caractères
    - va_list n'est pas à priori un char*.
    - va_list est lié aux fonctions dont le nombre de paramètres est indéterminé et qui sont extraits par les macros va_start, va_arg, va_end.
    Je ne vois pas ce qui cloche dans ce code, sauf que je ne voie pas non plus en quoi il est utile sauf à compliquer les choses.
    Exemple : somme d'une suite de nombre terminée par 0
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int sum(int val, ...)
    {
       int total = val;
       va_list ap ;
       int arg;
       va_start(ap, val);
       while ((arg = va_arg(ap,int)) != 0)  total += arg;
       va_end(ap);
       return total ;
    }
    Comment utiliser A :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int sum(int val, ...)
    {
       int total = val;
       va_list ap ;
       int arg;
       A *a;
       va_start(ap, val);
       a = A_new(ap);
       while ((arg = va_arg(a->ap,int)) != 0)  total += arg;
       va_end(a->ap);
       free(a);
       return total ;
    }
    Où est l'avantage ? on doit toujours faire le va_start sur une variable intermédiaire et en plus, on a le free à faire.
    Si quelqu'un peut coder de façon + astucieuse en utilisant A ou lui trouver un utilisation astucieuse...

  6. #6
    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 : 68
    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 ultimate_manx
    Voici une des questions de l'ancien exam de C de ma faq. Personne a trouvé le resultat et j'en ai marre de chercher sur google. Donc j'ai pensé à vous.

    Trouvez l'erreur de conception du code suivant.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    typedef struct _A A;
    struct _A{
       va_list ap;
    };
     
    A* A_new(va_list ap)
    {
       A* a=malloc(sizeof(*a));
       if(a)a->ap=ap;
       return a;
    }
    J'avoue que ce n'est pas facile. J'ai un doute sur les possibilité de 'copie' d'une variable de type va_list. Je ne sais pas si cette copie a un sens. Je dirais que c'est un usage inhabituel de va_list. Il faudrait fouiller la norme pour savoir si c'est possible, défini etc.

    http://www.open-std.org/JTC1/SC22/WG...docs/n1124.pdf

  7. #7
    Membre du Club
    Inscrit en
    Avril 2007
    Messages
    40
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 40
    Points : 46
    Points
    46
    Par défaut
    Dans un include sur mon poste j'ai ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #ifdef  _M_ALPHA
    typedef struct {
            char *a0;       /* pointer to first homed integer argument */
            int offset;     /* byte offset of next parameter */
    } va_list;
    #else
    typedef char *  va_list;
    #endif
    Donc je ne pense pas que son code utilise le paramètre ... avec va_list, va_arg, va_start ... il utilise juste le typdef pour char*.

  8. #8
    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 : 68
    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 Darwiz
    Donc je ne pense pas que son code utilise le paramètre ... avec va_list, va_arg, va_start ... il utilise juste le typdef pour char*.
    La définition exacte du type va_list dépend de l'implémentation (tu en as la preuve sous les yeux). On ne peut donc faire aucune hypothèse sur le type qui est derrière.

    J'ai trouvé ça sur mon disque :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef va_list __gnuc_va_list;

  9. #9
    Membre du Club
    Inscrit en
    Avril 2007
    Messages
    40
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 40
    Points : 46
    Points
    46
    Par défaut
    Je suis d'accord mais au vue du contexte et ayant testé la compil sur mon poste (Visual Studio 2003) il prend bien un char*.

    Par rapport au problème posé je pense qu'il sagit d'un problème d'allocation sur une structure contenant un pointeur.
    Problème de fac récurant ou tu dois tout réallouer et recopie.

    Après le prof peut être assez tordu et sortir que l'utilisation de va_list est maligne et donc qu'il faut tout changer.
    Mais bon ce que je peux en dire c'est que la définition que j'ai donné se trouve dans Visual dans plein de fichiers dont <stdio.h> ...

  10. #10
    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 : 68
    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 Darwiz
    Je suis d'accord mais au vue du contexte et ayant testé la compil sur mon poste (Visual Studio 2003) il prend bien un char*.
    Le P.O. n'a pas précisé que le problème était lié à une plateforme particulière...

  11. #11
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Sur le mien, va_list est défini comme un void*

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    En tout cas, merci de vos réponses, ca nous a permis d'avancer sur le problème

Discussions similaires

  1. [XL-2010] J'ai une erreur de compilation dans un de mes code VBA codes
    Par laitram69 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 22/04/2012, 11h19
  2. [Simulink][Débutante] Erreur de compilation dans un code
    Par karamellati dans le forum MATLAB
    Réponses: 4
    Dernier message: 30/05/2007, 12h47
  3. Réponses: 13
    Dernier message: 02/03/2007, 15h43
  4. Localiser une erreur d'exécution dans une DLL
    Par papadrago dans le forum C++Builder
    Réponses: 2
    Dernier message: 08/12/2006, 22h04
  5. Réponses: 4
    Dernier message: 08/06/2006, 10h26

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