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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    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
    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?

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    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 confirmé
    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
    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.

  4. #4
    Membre confirmé
    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
    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?

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    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 confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    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.

+ 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