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 :

Segmentation fault - Struct d'array


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Novembre 2011
    Messages : 25
    Par défaut Segmentation fault - Struct d'array
    Bonjour,

    Je chercher à utiliser un curseur qui fetch des données dans une struct de tableaux (PRO*C) mais j'ai une segmentation fault de c que j'aimerai élucider.

    Voici la struct que j'utilise :

    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
     
    /* Peut-être trouver une façon de faire dynamique ... */
     
    #define ARRAY_LENGTH 100
     
    /**************************** Struct definition ************************************************************/
     
    /* Structure de donnée représentant l'ensemble des tableaux utilisés pour stocker les données de rating_score. */
    typedef struct
    {
    	long		PersonIdn[ARRAY_LENGTH];
    	char 		RatingModel[ARRAY_LENGTH][CODE_LENGTH];
    	char		ModelVar[ARRAY_LENGTH][CODE_LENGTH];
    	char		ModelValue[ARRAY_LENGTH][51];	
    	long  	        RatingScoreSeq[ARRAY_LENGTH];
    	long		RequestNumber[ARRAY_LENGTH];
    } DataToInsert;
    Et le problème que j'ai est que si je change ARRAY_LENGTH et que je met cela à 1000, cela me fait une segmentation fault alors qu'a 100 ou même 200 comme indiqué, tout se passe bien.

    Une raison à cela?

    Merci beaucoup de votre aide et de votre temps,
    Albin.

    ps : j'ai pas forcément besoin d'utiliser une taille de 1000 mais j'aime pas laisser ce genre de question en suspens...

  2. #2
    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
    Avec le peu d'informations que tu communiques (valeur de CODE_LENGTH ? mode de création des variables DataToInsert ? code qui fait planter ?...), la seule chose qu'on puisse dire est que la taille de la structure est peut être alors trop grande pour être créée en allocation automatique (variable locale sur la pile).

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Novembre 2011
    Messages : 25
    Par défaut
    Comme j'ai dit, le problème vient de la taille de ARRAY_LENGTH qui devient trop grande.

    La valeur de CODE_LENGTH est de 10. Et comme j'ai dit aussi, la struct est remplie par un curseur de PRO*C :

    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
     
    	EXEC SQL CONTEXT USE :*ctx;
     
    	/* On déclare un curseur */
     
    	EXEC SQL WHENEVER SQLERROR DO OracleDBError();
    	EXEC SQL WHENEVER NOT FOUND DO break;
    	EXEC SQL DECLARE RatingScore_Curs CURSOR FOR
    		SELECT 	person_idn,
    						rating_model,
    						model_var,
    						model_value,
    						rating_score_seq,
    						request_number
    		FROM   		rating_score
    		ORDER BY person_idn,
    						rating_model,
    						model_var;
     
    	EXEC SQL OPEN RatingScore_Curs;
     
    	if (sqlca.sqlcode != 0)
    	{
    		printf("Error openning RatingScore_Curs - SqlCode : %d\n", sqlca.sqlcode);
    		return (void *) -1;
    	}
     
    	/* On ouvre le curseur et on fetch continuellement dans une struc d'array (DataToInsert) représentant une ligne. */
     
    	for(;;)
    	{
     
    		/* Structures de données utilisées pour le fetch :
     
    				-selectedData : les données récupérées.
    				-indicatorData : indicateur sur chaque champs permettant de savoir si la valeur retournée était NULL ou non (utilisé pour éviter une
    				ORA-1455).
    		*/
     
    		DataToInsert selectedData;
    		DataIndicator indicatorData;
     
    		EXEC SQL FETCH RatingScore_Curs INTO :selectedData:indicatorData;
     
    		 if (sqlca.sqlcode != 0)
    		{
    			printf("Error fetching RatingScore_Curs - SqlCode : %d\n", sqlca.sqlcode);
    			return (void *) -1;
    		}
    	}
    Et c'est ce bout de code qui plante (le seul à utiliser la struct pour le moment). Oui je me doutais que la valeur devait être trop grande mais même si c'est une struct de 6 tableaux, 6 tableaux de taille 1000 c'est quand même minuscule comparé à certain programme non? J'ai déjà traité des matrice bien plus gigantesque sans avoir aucune segmentation fault...

    Merci,
    Albin.

  4. #4
    Membre émérite
    Avatar de Elijha
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Avril 2003
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Avril 2003
    Messages : 314
    Par défaut
    Bonjour,

    Si je me rappel bien de mes cours de C, les variables globales sont stockées sur le tas. Pour un programme C, le tas est limité à 65536 octets. Si l'on prend la taille de ta structure en octets (avec un long à 4 octets par exemple, car cela peu changer d'une machine à une autre) on obtient :
    taille = (1000×4)+(1000×10x1)+(1000×10x1)+(1000×51x1)+(1000×4)+(1000×4) = 83000 octets
    Donc il te manque environs 17ko.

    Dans ce cas, il te reste plus que la solution de l'allocation dynamique de mémoire de ton tableau (malloc() et free()) qui te permettra d'utiliser beaucoup plus de mémoires.

    A toi de jouer et bonne continuation.

  5. #5
    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 je me rappel bien de mes cours de C, les variables globales sont stockées sur le tas
    Non. Elles sont stockées en général dans une zone "programme". Les allocations sur le tas sont obtenues par allocation dynamique.
    Pour un programme C, le tas est limité à 65536 octets.
    Tu confonds avec la pile utilisée par les variables en allocation automatique et qui est beaucoup plus limitée en taille que le tas (mais 65536 est bien peu)

    Les "grosses" variables doivent donc être créées en global ou par allocation dynamique.

  6. #6
    Membre averti
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Novembre 2011
    Messages : 25
    Par défaut
    Ce qui signifie que je dois soit créer ma struct en utilisant malloc/free ou alors la déclarer en globale donc... mais comment faire?

    Comme j'ai apprit la programmation en JAVA j'ai quelques souci avec les façons de faire plus bas niveau. Par exemple, comme je fais pour déclarer une struct avec des tailles de tableau dynamique?

    Par exemple en voulant créer une struct ayant 6tableaux de taille 10 et une autre avec des tableaux de taille 20? Je dois créer les tableaux et les donner à la truc à l'aide de pointeur ? Ou y'a il un moyen de le faire à l'intérieur même de la struct?

    Merci infiniment,
    Albin.

  7. #7
    Membre émérite
    Avatar de Elijha
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Avril 2003
    Messages
    314
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Avril 2003
    Messages : 314
    Par défaut
    Si je me rappel bien de mes cours de C, les variables globales sont stockées sur le tas
    mea culpa. C'est triste la vieillesse.

    Après quelques recherches (sur architecture x86) :
    • Segment de texte : code
    • Segment de données : variables statiques et globales
    • Segment bss : variables non initialisées
    • Segment de tas : variables allouées dynamiquement
    • Segment de pile : variables, appels de fonctions etc.

    [A vérifier] La taille maximum en allocation serai limitée à SIZE_MAX qui dépend de la machine (size_t). Pour une machine 32 bits, cela serait 4294967295 octets.


    En C l'allocation dynamique est très simple, mais il faut absolument vérifier l'état des pointeurs au retour des fonctions d'allocation et faire très attention lors de l'utilisation, car en C il n'y a pas contrôle. Tu peux facilement te retrouver à écrire dans une zone mémoire qui n'appartient pas au programme.
    Dans ton cas, il te faut déclarer une structure de pointeurs, puis attribuer ces pointeurs en fonction de la taille voulue
    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
    // Déclarations
    typedef struct
    {
        long    *PersonIdn ;
        char    *RatingModel ;
        char    *ModelVar ;
        char    *ModelValue ;	
        long    *RatingScoreSeq ;
        long    *RequestNumber;
    } DataToInsert ;
     
    DataToInsert table ;
     
    // Allocations
    table.PersonIdn = malloc(ARRAY_LENGTH * sizeof(long)) ;
    if(table.PersonIdn==NULL) {
        printf("Erreur d'allocation sur PersonIdn.\n") ;
        return -1 ;
    }
     
    table.RatingModel = malloc(ARRAY_LENGTH * CODE_LENGTH * sizeof(char)) ;
    if(table.RatingModel==NULL) {
        printf("Erreur d'allocation sur RatingModel.\n") ;
        free(table.PersonIdn) ;  // Libération avant la sortie
        return -1 ;
    }
     
    // etc...
    A la fin de ton programme, il faut libérer toute la mémoire qui a été précédemment allouée (fonction free).

    Bonne continuation.

  8. #8
    Membre chevronné Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Par défaut
    [A vérifier] La taille maximum en allocation serai limitée à SIZE_MAX qui dépend de la machine (size_t). Pour une machine 32 bits, cela serait 4294967295 octets.
    En théorie sur une machine x86, mais ce chiffre est bien plus faible il est limité par la mémoire physique et celle affecté au programme par l'OS, qui s'en garde une peu pour lui et les autres programmes programme.
    Tu peux facilement te retrouver à écrire dans une zone mémoire qui n'appartient pas au programme.
    Pour être un peu tatillon si ton OS est récent il est impossible de sortir de sa zone mémoire une exception sera levé avant. Mais en tout cas le résultat est le même il ne faut pas dépassé la taille alloué.

  9. #9
    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
    @Elijha :
    Dans ton cas, il te faut déclarer une structure de pointeurs, puis attribuer ces pointeurs en fonction de la taille voulue...
    Cette complication est inutile.

    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
    typedef struct
    {
    	long		PersonIdn[ARRAY_LENGTH];
    	char 		RatingModel[ARRAY_LENGTH][CODE_LENGTH];
    	char		ModelVar[ARRAY_LENGTH][CODE_LENGTH];
    	char		ModelValue[ARRAY_LENGTH][51];	
    	long  	        RatingScoreSeq[ARRAY_LENGTH];
    	long		RequestNumber[ARRAY_LENGTH];
    } DataToInsert; 
     
    // ----en globale
    DataToInsert table ;
    // ----ou en allocation dynamique :
    DataToInsert *table = malloc(sizeof *table) ;
    ....
    free(table);

  10. #10
    Membre averti
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Novembre 2011
    Messages : 25
    Par défaut
    Un grand merci à vous deux, je me sens déjà un peu plus à l'aise quand je joue avec les pointeurs et allocations dynamique !

    Albin.

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

Discussions similaires

  1. Segmentation Fault: struct in_addr
    Par garn_le_troisieme dans le forum C++
    Réponses: 5
    Dernier message: 08/06/2012, 09h40
  2. [SDL_Image] Img_Load : segmentation fault ....
    Par Mathieu.J dans le forum OpenGL
    Réponses: 6
    Dernier message: 19/10/2004, 23h52
  3. [REDHAT] Segmentation fault systematique
    Par mela dans le forum RedHat / CentOS / Fedora
    Réponses: 2
    Dernier message: 21/09/2004, 06h05
  4. Réponses: 13
    Dernier message: 13/07/2004, 15h41
  5. Comment contrer la "segmentation fault" ?
    Par guillaume_pfr dans le forum C
    Réponses: 15
    Dernier message: 08/08/2003, 13h43

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