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 :

Problème d'initialisation d'une structure


Sujet :

C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 13
    Par défaut Problème d'initialisation d'une structure
    Bonjour,

    Nous sommes en train d'essayer de réaliser une montée de version de compilateur en passant du gcc 2.96 au gcc 3.4.6.

    Lors d'un test, un traitement fonctionnel avec la compilation 2.96 produit une segmentation fault en 3.4.6.

    Après recherche, il semble que l'erreur vienne de l'initialisation d'une variable d'une structure d'erreur (la mise en commentaire de cette ligne permet au traitement de se dérouler sans soucis).

    La ligne est si basique que je ne comprends pas ce qui peut causer l'erreur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    strcpy( StructErr->NomSource ,  NOMFIC );
    sachant que #define NOMFIC "fichierlot.c"

    La structure stockant la variable est définie dans un autre fichier comme cela:

    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
    /* structure erreur */
    typedef struct {
        short AffichageEcran;           /* Flag =OK si on affiche a l'ecran */
        char FichierLog[100];           /* Chemin du fichier log */
        char NomTache[MAXTACHE];        /* nom de la tÀche */
        int  Cr;                        /* compte-rendu */
        int  Cerr;                      /* code erreur */
        char Cemet[20+1];               /* code emetteur */
        char Cdest[20+1];               /* code destinataire */
        char NomFic[MAXNOMFICH+1];      /* nom de fichier transmis */
        char NomBord[MAXNOMFICH+1];     /* nom du bordereau */
        char NomSource[MAXNOMFICH+1];   /* nom du fichier source */
        int  Ligne;                     /* numero de ligne */
        char Comment[700];              /* commentaire */
    } T_Erreur;
    typedef T_Erreur *pT_Erreur;
    En vous remerciant par avance pour votre aide.

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations forums :
    Inscription : Février 2010
    Messages : 87
    Par défaut
    je ne peut pas t'aider parce ce que je connais pas le français mais peut étre ton problème vien de la ?
    struct ma_structure {
    char champ1; /* 8 bits */
    int champ2; /* 32 bits */
    char champ3; /* 8 bits */
    };
    On pourrait penser que cette structure occupera 6 octets en mémoire, et pourtant, sur une bonne partie des
    compilateurs, on obtiendrait une taille plus proche des 12 octets.
    En fait, les compilateurs insèrent quasiment toujours des octets entre les champs pour pouvoir les aligner sur des
    adresses qui correspondent à des mots machines. Cela est dû à une limitation de la plupart des processeurs, qui ne
    peuvent lire des « mots » de plus d'un octet que s'ils sont alignés sur un certain adressage (alors qu'il n'y a pas de
    contrainte particulière pour lire un seul octet, si le type char est défini sur 8bit).
    En se représentant la mémoire comme un tableau continu, on peut tracer le dessin suivant:

    | bloc N | bloc N + 1 | bloc N + 2 |
    ---+---------------+---------------+---------------+---
    | a | b | c | d | e | f | g | h | i | j | k | l |
    ---+---------------+---------------+---------------+---

    Les cases a, b, c, ... représentent des octets, et les blocs des sections de 32 bits. Si on suppose qu'une variable de type
    ma_structure doive être placée en mémoire à partir du bloc numéro N, alors un compilateur pourra, pour des raisons
    de performance, placer champ1 en a, champ2 de e à h, et champ3 en i. Cela permettrait en effet d'accéder
    simplement à champ2: le processeur fournit des instructions permettant de lire ou d'écrire directement le bloc N + 1.
    Dans ce cas, les octets de b à d ne sont pas utilisés; on dit alors que ce sont des octets de bourrage (ou padding en
    anglais). Un autre compilateur (ou le même, appelé avec des options différentes) peut aussi placer champ2 de b à e,
    et champ3 en f, pour optimiser l'utilisation mémoire. Mais alors il devra générer un code plus complexe lors des
    accès à champ2, le matériel ne lui permettant pas d'accéder en une seule instruction aux 4 octets b à e.
    En fait il faut garder à l'esprit que toutes les variables suivent cette contrainte: aussi bien les variables locales aux
    fonctions, les champs de structures, les paramètres de fonctions, etc.
    L'existence d'octets de bourrage ainsi que leur nombre sont non seulement dépendants de l'architecture, mais aussi du
    compilateur. Cela dit, il est toujours possible de connaître la « distance » (offset) d'un champ par rapport au début de
    la structure, et ce, de manière portable. Pour cela il existe une macro, déclarée dans l'entête <stddef.h>:
    j'ai copier/coller ça bonne chance

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 13
    Par défaut
    Merci beaucoup de ta réponse.

    Effectivement, il est possible que d'une version à l'autre du compilateur, le paddage de stockage diffère et que ce soit cela qui me pose problème. Mais du coup, je ne vois pas vraiment comment je peux régler ce problème.

  4. #4
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2011
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2011
    Messages : 59
    Par défaut
    Salut

    je ne pense pas que ça soit un problème de pading comme suggéré par PIC16F877A étant donné que tu prends pour adresse de destination
    l'emplacement mémoire du membre NomSource, ça passera quelque soit le pading (ça ne serait pas le cas si l'offset était calculé manuellement)

    est ce qu'il ne s'agit pas d'écrasement mémoire dont ce crash est la révélation
    (StructErr est un bon pointeur ?,
    MAXNOMFICH n'est pas défini avec des valeurs différentes entre les deux fichiers ?)
    sinon peut être remplacer strcpy par strncpy , c'est plus safe mais je ne pense pas que ça résoud le cas

    Cdt

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations forums :
    Inscription : Février 2010
    Messages : 87
    Par défaut
    je pense que dans les paramètre de compilateur qu'il faut faire quel que chose

    par exemple dans ton compilateur définie par exemple un char = 32bits aulieu 8bits si tu as un cpu 32 et meme choses avec les autre types de variable

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 13
    Par défaut
    A priori, aucun problème avec MAXNOMFICH.

    De plus, si j'affiche NOMFIC avant. La variable est renseignée correctement et avec la bonne taille.

    J'ai testé à tout hasard strncpy () mais cela ne change rien.

    Je ne sais pas changer les paramètres de mon compilateur afin de tester la solution de stocker les char sur 32 bits au lieu de 8 bits. Aurais tu de la documentation qui pourrait me renseigner?

    Merci pour vos idées.

  7. #7
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2011
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2011
    Messages : 59
    Par défaut
    dans strcpy(dest, src)

    le problème peux se poser avec src si ça ne se termine pas avec le '\0', pour cela strncpy est bon pour éliminer ce risque

    sinon il reste à inspecter dest , est ce qu'il découle d'une allocation mémoire valide, se trouve bien à l'intérieur de la plage occupée par StructErr (qui elle même se trouve dans la zone mémoire allée)

    le fichier où la structure est allouée et celui où elle est utilisée sont compilés avec la même version gcc, y'a t-il quelque chose qui peut faire que l'adresse/contenu de la variable à l'allocation soit différent / à l'écriture via strcpy

    Bref plein de questions auquelles le debuggeur saura mieux de répondre

  8. #8
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    Avec aussi peu de code, on ne peut pas vraiment t'aider.

    le problème peux se poser avec src si ça ne se termine pas avec le '\0', pour cela strncpy est bon pour éliminer ce risque
    Le '\0' est forcément présent puisque :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #define NOMFIC "fichierlot.c"
    (...)
    strcpy( StructErr->NomSource ,  NOMFIC );
    Il nous faut le code qui précède ce fameux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    strcpy( StructErr->NomSource ,  NOMFIC );
    , depuis l'allocation mémoire.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 13
    Par défaut
    Voila la fonction:

    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
    int CreerZoneEnregFicLot( pT_Erreur StructErr, int Fp, pT_ZoneEnreg StructZone ) {
    	char	zone[1000];
    	int err;
     
    	/* Initialisation pour l'ecriture dans le fichier log */
    	strcpy (StructErr->NomSource, NOMFIC);
     
    	/* 
    	 * On verifie la taille de la zone
    	 * si elle est < StructZone.LngZone on padde le buffer a droite 
    	 * avec StructZone.Pad
    	 */
    	if ( strlen( StructZone->ValueZone ) < StructZone->LngZone )
    		PadADroite( StructZone->ValueZone , 	StructZone->Pad , 
    		            StructZone->LngZone ); 
     
     
    	/* Ecriture du debut de la zone */
    	sprintf( zone, "%05d%03d%05d%s",
    			StructZone->NumZone, StructZone->NbEnreg,
    			StructZone->LngZone, StructZone->ValueZone );
     
    	err = write( Fp , zone , strlen(zone) );
    	if ( err == -1 ) {
    		StructErr->Cr=ERRSYS;
    		StructErr->Cerr=errno;
    		StructErr->Ligne = __LINE__ ;
    		sprintf( StructErr->Comment , "Pb Ecriture zone N0<%d> du fichier lot",
    		         StructZone->NumZone );
    		EcrireCr(StructErr);
    		close( Fp );
    		return( NOK );
    	}
     
    	return( OK );
     
    }/* Fin de la fct CreerZoneEnregFicLot() */

    La constante NOMFIC est définie en début de fichier.
    La mise en commentaire de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	/* Initialisation pour l'ecriture dans le fichier log */
    	strcpy (StructErr->NomSource, NOMFIC);
    supprime la segmentation fault.


    La structure d'erreur est définie dans un autre fichier (code au dessus)

  10. #10
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2011
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2011
    Messages : 59
    Par défaut
    là il s'agit de la variable texte (dont on ne voit pas la définitions/allocation) et non StructErr->NomSource

    le problème est différent

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 13
    Par défaut
    Pardon c'est une erreur. J'ai mal nettoyé mon code avant de poster.
    J'ai édité le code afin qu'il corresponde à mon problème.

  12. #12
    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 ne vois guère comme possibilité que
    0- NOMFIC n'est pas correctement termné par 0 (Impossible ici)
    1- StructErr->NomSource est trop petit pour contenir NOMFIC (donc MAXNOMFICH <12)
    2- StructErr->NomSource et NOMFIC sont deux zones mémoires qui se recouvrent. (Impossible ici)
    3- StructErr est NULL (mais ce comportement aurait été visible avec gcc 2.96)
    4- StructErr n'est pas NULL mais n'est pas l'adresse d'un T_Erreur
    5- StructErr n'est pas NULL mais est l'adresse d'un T_Erreur qui n'existe plus
    6- L'erreur n'a pas de rapport direct avec cette ligne de code. Elle est le fait d'un comportement indéterminé ailleurs mais qui se manifeste à cette occasion.

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 13
    Par défaut
    Citation Envoyé par diogene Voir le message
    je ne vois guère comme possibilité que
    0- NOMFIC n'est pas correctement termné par 0 (Impossible ici)
    1- StructErr->NomSource est trop petit pour contenir NOMFIC (donc MAXNOMFICH <12)
    2- StructErr->NomSource et NOMFIC sont deux zones mémoires qui se recouvrent. (Impossible ici)
    3- StructErr est NULL (mais ce comportement aurait été visible avec gcc 2.96)
    4- StructErr n'est pas NULL mais n'est pas l'adresse d'un T_Erreur
    5- StructErr n'est pas NULL mais est l'adresse d'un T_Erreur qui n'existe plus
    6- L'erreur n'a pas de rapport direct avec cette ligne de code. Elle est le fait d'un comportement indéterminé ailleurs mais qui se manifeste à cette occasion.
    J'en arrive à la même conclusion que toi:

    0: comme tu le dis, avec le strcpy() ça parait impossible
    1: MAXNOMFICH vaut 30
    2: pas mieux
    3: pas mieux
    4: non j'ai vérifié, ce n'est aps le cas
    5: T_Erreur existe bel et bien
    6: j'imagine qu'il ne reste que ça... Mais la reproductibilité de la chose me laisse perplexe. J'ai changé les cas tests. La mise en commentaire de la ligne fait toujours disparaitre la segmentation fault...

    Je continue à chercher, je reviendrai vers vous si je trouve la réponse.

    Merci pour votre aide

  14. #14
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Schnouf00 Voir le message
    Mais la reproductibilité de la chose me laisse perplexe. J'ai changé les cas tests. La mise en commentaire de la ligne fait toujours disparaitre la segmentation fault...
    C'est que ça se passe avant..

    Moi ce que je vois qui pourrait poser problèe est :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        char FichierLog[100];           /* Chemin du fichier log */
        char NomTache[MAXTACHE];        /* nom de la tÀche */

    100 pour un chemin c'est bien court..

    D'autre part MAXTACHE vaut quoi ?

    Pour le reste, il faut debugger et à mon avis à l'aide d'un debugger (style ddd si tu es sur Linux) imprimer la structure à l'endroit où ça crashe et regarder quel champ n'est pas correct..

  15. #15
    Membre actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations forums :
    Inscription : Février 2010
    Messages : 87
    Par défaut
    Citation Envoyé par Schnouf00 Voir le message
    .

    Je ne sais pas changer les paramètres de mon compilateur afin de tester la solution de stocker les char sur 32 bits au lieu de 8 bits. Aurais tu de la documentation qui pourrait me renseigner?
    paramétres se trouve dans le ficher limits.h et voici le lien ou j'ai trouvé le texte
    http://fr.wikibooks.org/wiki/Program...s_avanc%C3%A9s peut étres
    trouver des chose qui vous aider a localiser le problème bonne chance

  16. #16
    Inactif  
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 123
    Par défaut character-set UTF-8 ?
    Bonjour,
    Je ne suis pas sûr mais il y a peut-être une hypothèse. Ce serait que
    #define NOMFIC "test.txt"
    serait encodé en UTF-8. Du coup, un strcpy ne convient plus mais un wstrcpy oui.
    GCC preprocessor et chercher encoding

  17. #17
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 13
    Par défaut
    Je ne vous ai pas oublié et je vous remercie pour votre aide, je n'ai malheuresement pas encore la solution.

    Ce n'est à priori pas un soucis d'encodage mais bien un problème de mémoire dans la structure.

    En effet, si j'augmente la taille d'un des char de la structure, la segmentation fault disparait.
    Mais au debuggage, aucune des variables de la structure semble dépasser la taille allouée...

  18. #18
    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
    si j'augmente la taille d'un des char de la structure, la segmentation fault disparait.
    Comme les membres d'une structure sont placés en mémoire dans l'ordre de leur déclaration, on peut envisager un débordement lors d'une écriture dans ce tableau ce qui pourrait écraser ou altérer la variable membre suivante.
    Recherche donc toutes les écritures faites dans ce tableau pour vérifier que le tableau n'est pas trop petit (sans oublier un éventuel '\0' si ce sont des chaines de caractères)

  19. #19
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 13
    Par défaut
    Nous avons résolu ce problème en utilisant une nouvelle structure d'erreur différente dans l'appel à la fonction.
    Les pointeurs se perdaient lorsqu'on fait un appel de fonction dans une fonction appelée en utilisant la même structure d'erreur.
    Je vous remercie tous pour votre aide.

  20. #20
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    à mon humble avis cela n'a pas résolu le problème..

    Il est sans doute moins visible, mais la raison pour laquelle "Les pointeurs se perdaient lorsqu'on fait un appel de fonction dans une fonction appelée en utilisant la même structure d'erreur." doit toujours être là, posant la potentialité d'une erreur plus tard...

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

Discussions similaires

  1. initialisation d'une structure
    Par ryadh.naouar dans le forum C
    Réponses: 3
    Dernier message: 29/10/2007, 15h21
  2. Réponses: 17
    Dernier message: 09/03/2007, 18h13
  3. Problème d'initialisation d'une matrice ?
    Par wilval dans le forum C
    Réponses: 5
    Dernier message: 04/02/2007, 16h13
  4. [Linux]problème d'affectation d'une structure
    Par cimcim dans le forum Linux
    Réponses: 5
    Dernier message: 11/12/2006, 17h13
  5. [Initialisation] Remplir une structure une fois
    Par Kimael dans le forum Langage
    Réponses: 14
    Dernier message: 08/06/2004, 15h33

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