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 :

va_list problème sous linux, pas sous windows


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2004
    Messages : 58
    Points : 68
    Points
    68
    Par défaut va_list problème sous linux, pas sous windows
    bonjour à tous,

    Je suis en train de porter un code en C depuis windows vers linux, et je me retrouve avec des segmentation faults que j'ai du mal à comprendre.
    Voici un code qui fonctionne sous windwos mais me donne un seg fault sous linux:
    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
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
     
    #define CRLF "\n"
    #define VERSION_DATE "2012SEP10"
    #define MANNO 1
    #define ERR_MSG_MAX_LENGTH 10000
     
    typedef struct
    {
      char name[255];
      char birth_date[255];
    }SOMEONE;
    typedef struct
    {
      char name[255];
      int version;
    }APPLICATION;
     
    SOMEONE *him;
    APPLICATION *that;
     
    FILE  *fplog = NULL;
     
    int file_exists(char *filename)
    {
      FILE  *fp;
     
      if ((fp = fopen(filename, "r")) == NULL)
        return 0;
      else
      {
        fclose(fp);
        return 1;
      }
    }
     
    int msg_handler( long code, const char *format, va_list args)
    {
      char      fmt[ERR_MSG_MAX_LENGTH];
      int       ret = 0;
     
        if (code > 0) /*print on the console if code >0*/
          vprintf(format, args);
     
        /*whatever print to file*/
        sprintf(fmt, "%d\t%s" CRLF, code, format);
        vfprintf(fplog,fmt, args);/*he if I have already printed to the console, I get SEGFAULT with linux*/
        ret |= 2;
     
      return ret;
    }
     
    void trc_msg( long code, const char *format, ...)
    {
      int ret;
      va_list args;
     
        va_start(args, format);
        ret = msg_handler(code, format, args);
        va_end(args);
    }
     
     
    int main()
    {
      int i = 0;
     
        if (file_exists("./test.log"))
          fplog = fopen("./test.log", "a+");
        else
        {
          fplog = fopen("./test.log", "w");
          if (fplog)
            fprintf(fplog, "CODE\tDESCRIPTION" CRLF);
        }
        him = calloc(1, sizeof(SOMEONE));
        that = calloc(1, sizeof(APPLICATION));
     
        for (i=0; i<2; i++)
        {
          sprintf(him->name,"robot%d", i);
          strcpy(him->birth_date, VERSION_DATE);
          strcpy(that->name,"Super2000");
          that->version = 1;
     
          trc_msg( i, "Mr: %s was created on %s using application: %s[%d]", him->name, him->birth_date, that->name, that->version);
        }
     
     
        fclose(fplog);
        free(him);
        free(that);
        return 0;
    }
    il semblerait sous linux (ubuntu 10.05 64bits)
    je ne puisse pas faire 2 appels consécutifs aux arguments de ma va_list dans la même fonction, tandis que sous windows, ça ne pose aucun problème.

    Quelqu'un aurait-il une explication?
    Comment puis-je tester si un appel à ma va_list va terminer sur un SEGFAULT?
    Au paradis, on est assis à la droite de Dieu.
    C'est normal, c'est la place du mort
    - [Pierre Desproges]

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Il manque l'inclusion de string.h.

    Avec ou sans, sous Linux Mint 13, je n'ai pas d'erreur de segmentation. Ce n'est donc pas une histoire de Windows ou de Linux mais de chance.

    As-tu essayé de passer ton programme dans Valgrind ?

  3. #3
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2004
    Messages : 58
    Points : 68
    Points
    68
    Par défaut
    merci bktero,

    J'ai ajouté string.h, mais ça ne change rien.

    Visblement effectivement, ce serait une question de chance.
    en épluchant les man page, je vois:
    The functions vprintf, vfprintf, vsprintf, vsnprintf are
    equivalent to the functions printf, fprintf, sprintf, snprintf, respectively,
    except that they are called with a va_list instead of a variable
    number of arguments. These functions do not call the va_end macro.
    Consequently, the value of ap is undefined after the call. The application
    should call va_end(ap) itself afterwards
    Ce qui voudrait dire que le premier appel à vprintf fait que la valeur de args est indéterminée pour le second appel à vprintf.

    j'ai changé mon code en désepor de cause:
    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
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    #include <string.h> /*ajout*/
     
    #define CRLF "\n"
    #define VERSION_DATE "2012AUG10"
    #define MANNO 1
    #define ERR_MSG_MAX_LENGTH 10000
     
    typedef struct
    {
      char name[255];
      char birth_date[255];
    }SOMEONE;
    typedef struct
    {
      char name[255];
      int version;
    }APPLICATION;
     
    SOMEONE *him;
    APPLICATION *that;
     
    FILE  *fplog = NULL;
     
    int file_exists(char *filename)
    {
      FILE  *fp;
     
      if ((fp = fopen(filename, "r")) == NULL)
        return 0;
      else
      {
        fclose(fp);
        return 1;
      }
    }
     
    int msg_handler( long code, const char *format, va_list args)
    {
      char      fmt[ERR_MSG_MAX_LENGTH];
      int       ret = 0;
     
        if (code > 0) /*print on the console if code >0*/
        {
          vprintf(format, args);
          va_end(args);/*ajout*/
        }
     
        /*whatever print to file*/
        sprintf(fmt, "%d\t%s" CRLF, code, format);
        vfprintf(fplog,fmt, args);
        ret |= 2;
     
      return ret;
    }
     
    void trc_msg( long code, const char *format, ...)
    {
      int ret;
      va_list args;
     
        va_start(args, format);
        ret = msg_handler(code, format, args);
        va_end(args);
    }
     
     
    int main()
    {
      int i = 0;
     
        if (file_exists("./test.log"))
        fplog = fopen("./test.log", "a+");
        else
        {
          fplog = fopen("./test.log", "w");
          if (fplog)
            fprintf(fplog, "CODE\tDESCRIPTION" CRLF);
        }
        him = calloc(1, sizeof(SOMEONE));
        that = calloc(1, sizeof(APPLICATION));
        for (i=0;i<2;i++)
        {
          sprintf(him->name,"robot%d", i);
          strcpy(him->birth_date, VERSION_DATE);
          strcpy(that->name,"Super2000");
          that->version = 1;
     
          trc_msg( i, "Mr: %s was created on %s using application: %s[%d]", him->name, him->birth_date, that->name, that->version);
        }
     
     
        fclose(fplog);
        free(him);
        free(that);
        return 0;
    }
    mais bien entendu, ça ne change rien.

    mon linux:
    uname -a:
    Linux 2.6.32-43-generic #97-Ubuntu SMP Wed Sep 5 16:42:26 UTC 2012 x86_64 GNU/Linux

    Quelqu'un aurait il un problème équivalent?

    Je voudrais bien faire un test avec valgrind, mais ppour celà, il va falloir que je trouve un tuto valgrind, jecherche ça.
    Au paradis, on est assis à la droite de Dieu.
    C'est normal, c'est la place du mort
    - [Pierre Desproges]

  4. #4
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2004
    Messages : 58
    Points : 68
    Points
    68
    Par défaut
    bon, je viens de lancer valgrind pour un memcheck:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    valgrind --version
    valgrind-3.6.0.SVN-Debian
    valgrind  --leak-check=full --track-origins=yes --xml=yes --xml-file=/home/gigi/workspace/test/ValgrindOut.xml "/home/gigi/workspace/test/bin/Debug/test"
    et voici ce que ça me donne

    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
    UninitCondition          ====          Conditional jump or move depends on uninitialised value(s)
    Call stack:
    /build/buildd/eglibc-2.11.1/stdio-common/vfprintf.c          1617  0x56219C3: vfprintf
    /home/gigi/workspace/test/main.c          52                       0x40093F: msg_handler
    /home/gigi/workspace/test/main.c          64                       0x400A34: trc_msg
    /home/gigi/workspace/test/main.c          90                       0x400BB4: main
    Uninitialised value was created by a stack allocation
    /home/gigi/workspace/test/main.c          70                       0x400A3D: main
    UninitValue                                   ====                     Use of uninitialised value of size 8
    Call stack:
    /build/buildd/eglibc-2.11.1/stdio-common/vfprintf.c           1617 0x5623E32: vfprintf
    /home/gigi/workspace/test/main.c          52                       0x40093F: msg_handler
    /home/gigi/workspace/test/main.c          64                       0x400A34: trc_msg
    /home/gigi/workspace/test/main.c          90                       0x400BB4: main
                                         Uninitialised value was created by a stack allocation
    /home/gigi/workspace/test/main.c          70                       0x400A3D: main
    InvalidRead                                    ====             Invalid read of size 1 Call stack:
    /build/buildd/eglibc-2.11.1/stdio-common/vfprintf.c          1617 0x5623E32: vfprintf
    /home/gigi/workspace/test/main.c          52                      0x40093F: msg_handler
    /home/gigi/workspace/test/main.c          64                      0x400A34: trc_msg
    /home/gigi/workspace/test/main.c          90                      0x400BB4: main
    Address  0x100400770 is not stack'd, malloc'd or (recently) free'd
    ||Valgrind found 3 errors!
    Je dois dire que je n'y comprends pas grand chose.
    Est ce que ça vous parle?
    Au paradis, on est assis à la droite de Dieu.
    C'est normal, c'est la place du mort
    - [Pierre Desproges]

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Je n'observe pas les erreurs que tu as, avec les mêmes options pour Valgrind....

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    pierre@pierre-mint:~/Documents/TestsC$ valgrind --version
    valgrind-3.7.0
    pierre@pierre-mint:~/Documents/TestsC$ uname -a
    Linux pierre-mint 3.2.0-23-generic #36-Ubuntu SMP Tue Apr 10 20:41:14 UTC 2012 i686 athlon i386 GNU/Linux
    Je ne pourrais donc pas t'aider plus : /

  6. #6
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Il faut un va_start par parcours. OK, tu peux copier un va_list avec va_copy, mais c'est du C99 et je ne suis pas sur que MS l'implemente.

    Pour permettre de traiter le cas des parametres passes par registre, un va_list est souvent un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    typedef struct __valist va_list[1];
    l'effet est d'etre passe par reference plutot que par valeur sans marquage. En passant, GMP utilise le meme truc.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    Hello,

    Ceci ne peut pas fonctionner :

    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
    22
    23
    24
    25
    26
    27
    28
    int msg_handler( long code, const char *format, va_list args)
    {
      char      fmt[ERR_MSG_MAX_LENGTH];
      int       ret = 0;
     
        if (code > 0) /*print on the console if code >0*/
        {
          vprintf(format, args);
          va_end(args);/*ajout*/
        }
     
        /*whatever print to file*/
        sprintf(fmt, "%d\t%s" CRLF, code, format);
        vfprintf(fplog,fmt, args);
        ret |= 2;
     
      return ret;
    }
     
    void trc_msg( long code, const char *format, ...)
    {
      int ret;
      va_list args;
     
        va_start(args, format);
        ret = msg_handler(code, format, args);
        va_end(args);
    }

    • En ligne 9, tu fais un va_end() alors que la fonction appelante (trc_msg()) va en faire un également. Comme tu ne peux pas garantir que ces deux structures ne pointent pas, en interne, la même chose, ça risque de planter. C'est pourquoi C99 propose va_copy().
    • Les lignes 9 et 14 ne sont pas mutuellement exclusives : la seconde appelle donc vfprintf() avec une va_list « args » déja modifiée par la première. Et comme le parcours de la pile, pour retrouver les arguments, se fait exclusivement en faisant confiance au format passé, là encore, il y a dépassement.


    Si tu veux écrire à la fois sur la console et sur la sortie standard, soit tu utilises va_copy(), soit tu écris ta chaîne finale dans un buffer et tu écris celui vers les deux destinations avec fputs().

  8. #8
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2004
    Messages : 58
    Points : 68
    Points
    68
    Par défaut
    Merci pour vos réponses, j'ai décidé d'utiliser la macro va_copy, et ça fonctionne.

    Voici le code corrigé:
    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
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    #include <string.h>
     
    #define CRLF "\n"
    #define VERSION_DATE "2012AUG10"
    #define MANNO 1
    #define ERR_MSG_MAX_LENGTH 10000
     
    typedef struct
    {
      char name[255];
      char birth_date[255];
    }SOMEONE;
    typedef struct
    {
      char name[255];
      int version;
    }APPLICATION;
     
    SOMEONE *him;
    APPLICATION *that;
     
    FILE  *fplog = NULL;
     
    int file_exists(char *filename)
    {
      FILE  *fp;
     
      if ((fp = fopen(filename, "r")) == NULL)
        return 0;
      else
      {
        fclose(fp);
        return 1;
      }
    }
     
    int msg_handler( long code, const char *format, va_list args)
    {
      char      fmt[ERR_MSG_MAX_LENGTH];
      int       ret = 0;
      va_list   args_copy;
     
        va_copy(args_copy, args);
     
        if (code > 0) /*print on the console if code >0*/
        {
          vprintf(format, args_copy);
          va_end(args_copy);
        }
     
        /*whatever print to file*/
        sprintf(fmt, "%d\t%s" CRLF, code, format);
        va_copy(args_copy, args);
        vfprintf(fplog,fmt, args_copy);
        va_end(args_copy);
        ret |= 2;
     
      return ret;
    }
     
    void trc_msg( long code, const char *format, ...)
    {
      int ret;
      va_list args;
     
        va_start(args, format);
        ret = msg_handler(code, format, args);
        va_end(args);
    }
     
     
    int main()
    {
      int i = 0;
     
        if (file_exists("./test.log"))
        fplog = fopen("./test.log", "a+");
        else
        {
          fplog = fopen("./test.log", "w");
          if (fplog)
            fprintf(fplog, "CODE\tDESCRIPTION" CRLF);
        }
        him = calloc(1, sizeof(SOMEONE));
        that = calloc(1, sizeof(APPLICATION));
        for (i=0;i<2;i++)
        {
          sprintf(him->name,"robot%d", i);
          strcpy(him->birth_date, VERSION_DATE);
          strcpy(that->name,"Super2000");
          that->version = 1;
     
          trc_msg( i, "Mr: %s was created on %s using application: %s[%d]", him->name, him->birth_date, that->name, that->version);
        }
     
     
        fclose(fplog);
        free(him);
        free(that);
        return 0;
    }
    @ Jean-Marc
    ce code fonctionne aussi bien sous linux que sous windows.
    Par contre je ne comprends pas très bien ta proposition.
    Chez moi va_list est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef _G_va_list va_list;
    je ne comprends pas trop quel truc utilise GMP (qui c'est au fait?)

    @Obsidian
    oui, je me doutais bien que ça ne pouvait fonctionner. Cependant, je ne comprends toujours pas pourquoi le second vf_printf ne fonctionne pas.
    Le premier ne fait que "parser" les arguments sans les modifier.

    voici un second exemple avec l'utilisation de 2 vprintf /vfprintf. Le premier appel ne fait qu'afficher à la console un message qui n'a rien à voir avec ma va_list. Pourtant là encore, j'ai un segmentation fault.
    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
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    #include <string.h>
     
    #define CRLF "\n"
    #define VERSION_DATE "2012AUG10"
    #define MANNO 1
    #define ERR_MSG_MAX_LENGTH 10000
     
    typedef struct
    {
      char name[255];
      char birth_date[255];
    }SOMEONE;
    typedef struct
    {
      char name[255];
      int version;
    }APPLICATION;
     
    SOMEONE *him;
    APPLICATION *that;
     
    FILE  *fplog = NULL;
     
    int file_exists(char *filename)
    {
      FILE  *fp;
     
      if ((fp = fopen(filename, "r")) == NULL)
        return 0;
      else
      {
        fclose(fp);
        return 1;
      }
    }
     
    int msg_handler( long code, const char *format, va_list args)
    {
      char      fmt[ERR_MSG_MAX_LENGTH];
      int       ret = 0;
     
     
        if (code > 0) /*print on the console if code >0*/
        {
          vprintf("test:%d" CRLF, code);
        }
     
        /*whatever print to file*/
        sprintf(fmt, "%d\t%s" CRLF, code, format);
        vfprintf(fplog,fmt, args);
     
        ret |= 2;
     
      return ret;
    }
     
    void trc_msg( long code, const char *format, ...)
    {
      int ret;
      va_list args;
     
        va_start(args, format);
        ret = msg_handler(code, format, args);
        va_end(args);
    }
     
     
    int main()
    {
      int i = 0;
     
        if (file_exists("./test.log"))
        fplog = fopen("./test.log", "a+");
        else
        {
          fplog = fopen("./test.log", "w");
          if (fplog)
            fprintf(fplog, "CODE\tDESCRIPTION" CRLF);
        }
        him = calloc(1, sizeof(SOMEONE));
        that = calloc(1, sizeof(APPLICATION));
        for (i=0;i<2;i++)
        {
          sprintf(him->name,"robot%d", i);
          strcpy(him->birth_date, VERSION_DATE);
          strcpy(that->name,"Super2000");
          that->version = 1;
     
          trc_msg( i, "Mr: %s was created on %s using application: %s[%d]", him->name, him->birth_date, that->name, that->version);
        }
     
     
        fclose(fplog);
        free(him);
        free(that);
        return 0;
    }
    Et là, je ne comprends vraiment pas pourquoi. Et surtout, pourqu'oi j'ai le problème sur les linux 64 mais pas sur les 32 ni sur windows.
    Au paradis, on est assis à la droite de Dieu.
    C'est normal, c'est la place du mort
    - [Pierre Desproges]

  9. #9
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 370
    Points : 23 625
    Points
    23 625
    Par défaut
    Citation Envoyé par gigiskhan Voir le message
    @Obsidian
    oui, je me doutais bien que ça ne pouvait fonctionner. Cependant, je ne comprends toujours pas pourquoi le second vf_printf ne fonctionne pas.
    Le premier ne fait que "parser" les arguments sans les modifier.
    Justement parce que pour parser les arguments, toi ou vprintf devez appeler va_args() qui, lui, modifie ta va_list pour savoir où il en est. Donc, au deuxième appel, ta va_list est déjà au bout des arguments et la passer une deuxième fois conduit inévitablement à des résultats indéterminés.

    Il faut bien se rendre compte qu'il ne s'agit que de macros, qui sont nécessairement très rudimentaires. Et le C, lui, se contente de déposer les valeurs des arguments à la suite dans la pile. Les fonctions ordinaires parviennent à les retrouver parce qu'elles suivent leur prototype défini à l'avance. Autrement dit, d'une certaine manière, une va_list n'est rien d'autre qu'un pointeur qui pointe juste après le « dernier » argument lors de va_start, et qui est augmenté à chaque fois de la taille du type que tu passes à va_arg. Si tu te trompes, le compilo n'a aucun moyen de le savoir.

    Et là, je ne comprends vraiment pas pourquoi. Et surtout, pourqu'oi j'ai le problème sur les linux 64 mais pas sur les 32 ni sur windows.
    L'implémentation de ces macros est indéfinie. Et la man page de stdarg.h indique qu'elles remplacent déjà les varargs. On ne peut donc pas en tirer facilement de conclusions valables.

  10. #10
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par gigiskhan Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        va_copy(args_copy, args);
     
        if (code > 0) /*print on the console if code >0*/
        {
          vprintf(format, args_copy);
          va_end(args_copy);
        }
    Il manque un va_end quand code <= 0.

    @ Jean-Marc
    ce code fonctionne aussi bien sous linux que sous windows.
    Par contre je ne comprends pas très bien ta proposition.
    Ma proposition etait d'utiliser va_copy. Le reste n'etait qu'une note expliquant pourquoi meme quand tu passes un va_list a une fonction, elle peut le modifier.

    Citation Envoyé par Obsidian Voir le message
    Il faut bien se rendre compte qu'il ne s'agit que de macros, qui sont nécessairement très rudimentaires.
    C'est pas necessairement des macros et ca peut etre complique. La man page sous Linux parle de systemes ou va_start et va_copy font de l'allocation dynamique et va_end libere la memoire.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Oui, autant sortir le va_end du if().

    Et tant que j'y suis, voici le passage de la norme correspondant:

    Citation Envoyé par La norme, livre 7, chapitre 7:15, verset 3
    The object ap may be passed as an argument to another function; if that function invokes the va_arg macro with parameter ap, the value of ap in the calling function is indeterminate and shall be passed to the va_end macro prior to any further reference to ap.
    (je n'étais moi-même pas au courant de ce détail)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2004
    Messages : 58
    Points : 68
    Points
    68
    Par défaut
    un grand merci à vous pour vos explications, ça me semble beaucoup plus clair.

    Il faut effectivement sortir le va_end du if.

    Merci donc jean-marc, Médinoc et Obsidian
    Au paradis, on est assis à la droite de Dieu.
    C'est normal, c'est la place du mort
    - [Pierre Desproges]

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

Discussions similaires

  1. [Prob] code qui fonctionne sous windows mais pas sous linux
    Par hannibal.76 dans le forum Multimédia
    Réponses: 3
    Dernier message: 07/02/2011, 17h46
  2. Mon fichier gtkrc fonctionne sous windows mais pas sous Linux !
    Par Kicker dans le forum GTK+ avec C & C++
    Réponses: 2
    Dernier message: 24/04/2009, 12h54
  3. Réponses: 15
    Dernier message: 01/05/2007, 00h54
  4. [Systeme] Process marche sous windows, pas sous linux
    Par Zapan dans le forum Général Java
    Réponses: 12
    Dernier message: 14/01/2006, 13h06

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