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 :

segfault dépassement tableau ?


Sujet :

C

  1. #1
    Modérateur
    Avatar de ggnore
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    2 472
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 2 472
    Points : 4 029
    Points
    4 029
    Par défaut segfault dépassement tableau ?
    Bonjour.

    ça fait des mois que j'ai pas fait de langage C, et je suis déjà tout rouillé.
    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
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
     
    void erreur(char * msg){
            printf ("\n Erreur : %s\n", msg);
    }
     
    void affiche(char * msg){
            printf ("\n-------------------------------\n");
            printf ("%s",msg);
            printf ("\n-------------------------------");
    }
     
    int     lire_ligne( int * lot_n, float * cout_n)
    {
            char * dummy;
            char chaine[128];
     
            char * lot_c;
            char * cout_c;
     
            if(fgets(chaine, 128, stdin) == NULL){
                    erreur("fgets");
                    return -1;
            }
     
            lot_c = strtok (chaine,":");
            cout_c = strtok (NULL, ":");
     
            *lot_n = strtol ( lot_c, &dummy, 10);
            *cout_n = atof(cout_c);
            return 0;
    }
     
    int traitement (float ** tableau_resultat, int nb_ligne){
     
            char tmp[128];
            float chaine_cout[1024];
     
     
            int lot_courant=0;
            int nb_prod_par_lot=0;
            int nb_prod_tot=0;
            int ligne_faite=0, ligne_lue=0;
            int prod_traite=0;
     
            float max, min;
            float cout_lot;
     
            float test;
     
            int lot_n=-1;
            float cout_n;
     
            // tant qu'on n'a pas parcouru et traite tous les produits (et donc tous les lots)
            while (ligne_faite < nb_ligne){
     
                    cout_lot = 0;
     
                    if (lot_n != lot_courant)
                            lire_ligne(&lot_n, &cout_n);
     
                    sprintf(tmp,"\n%d. =>lot: %d >cout: %f ¹", ligne_lue, lot_n, cout_n);
                    affiche(tmp);
     
                    lot_courant = lot_n;
                    max = min = cout_n;
                    chaine_cout[ligne_lue] = cout_n;
                    cout_lot += cout_n;
     
                    nb_prod_par_lot++;
                    ligne_lue++;
     
                    // tant qu'on n'a pas parcouru tous les produits d'un lot
                    while (lot_courant == lot_n){
                            lire_ligne(&lot_n, &cout_n);
                            sprintf(tmp,"\n%d. =>lot: %d >cout: %f ²", ligne_lue, lot_n, cout_n);
                                    affiche(tmp);
     
                            if (lot_courant != lot_n) continue;
     
                            if (max<cout_n) max=cout_n;
                            if (min>cout_n) min=cout_n;
                            chaine_cout[ligne_lue]=cout_n;
                            nb_prod_par_lot++;
                            cout_lot+=
                            ligne_lue++;
                    }
     
                    // calcul des notes
                    for (prod_traite = 0 ; prod_traite < nb_prod_par_lot ; prod_traite++){
                            sprintf(tmp,"calcul de notre pour le %deme produit, cout=%f max=%f min=%f", prod_traite, chaine_cout[prod_traite], max, min);
                            affiche(tmp);
                            if (max==min) {chaine_cout[prod_traite] = 5;}
                            // si le cout est minimum on a un 10
                            else if (chaine_cout[prod_traite] == min)               {*tableau_resultat[prod_traite] = 10;}
                            // si le cout est max, on a un 1
                            else if (chaine_cout[prod_traite] == max)       {*tableau_resultat[prod_traite] = 1;}
                            // sinon on calcule relativement
                            else {
                                    /*
                                    sprintf(tmp, "10 - (10 * ( %f - %f)/(%f-%f))", chaine_cout[prod_traite], min, max,min);
                                    affiche(tmp);
     
                                    test=chaine_cout[prod_traite] - min;
                                    sprintf(tmp, "chaine_cout[prod_traite] - min = %f", test );
                                    affiche(tmp);
     
                                    test=max-min;
                                    sprintf(tmp, "max-min=%f", test);
                                    affiche(tmp);
     
                                    sprintf(tmp, "(chaine_cout[prod_traite] - min)/(max-min) = %f", (chaine_cout[prod_traite] - min)/(max-min) );
                                    affiche(tmp);
                                    */
                                    *tableau_resultat[prod_traite] = 10 - (10 * (chaine_cout[prod_traite] - min)/(max-min));
                            }
                            sprintf(tmp, "note: %f / 10", *tableau_resultat[prod_traite]);
                            affiche(tmp);
                    }
                    ligne_faite+=prod_traite-1;
                    nb_prod_par_lot=0;
     
            }
     
            return(0);
     
    }
     
    int main(int argc, char *argv[])
    {
            int nb_ligne=0;
            int curseur;
     
            char tmp[64];
            char * dummy;
            float * tableau_resultat;
     
            if (argc == 2){
                    printf ("argv[1]=%s", argv[1]);
                    nb_ligne=strtol(argv[1], &dummy, 10);
                    sprintf(tmp, "nb_l=%d", nb_ligne);
                    affiche(tmp);
            }
            else {
                    sprintf(tmp,"arguments > besoin du nombre de ligne, argc=%d", argc);
                    erreur(tmp);
                    return -1;
            }
     
            if ( (tableau_resultat = malloc ( sizeof(float) * nb_ligne)) == NULL ){
                    sprintf(tmp,"allocation tableau %d elements", nb_ligne);
                    erreur(tmp);
                    return -1;
            }
     
            sprintf(tmp,"allocation tableau %d elements", nb_ligne);
            affiche(tmp);
     
     
            sprintf(tmp,"lecture");
            affiche (tmp);
     
            traitement( &tableau_resultat, nb_ligne);
     
            return 0;
    }
    je travaille sous linux.
    mon fichier entree contient :
    1:1.54
    1:1.65
    1:2.05
    1:1.40556
    1:1.4
    1:1.5
    1:2.49
    1:2.02
    1:1.65
    2:1.76
    2:1.76
    2:1.76
    2:1.76
    2:1.8
    2:2.13
    2:1.26776
    2:1.5
    2:1.6
    2:2.7
    2:2.09
    2:1.8
    pour lancer mon programme, je fais :
    Quand le calcul commence, mon programme ne calcule que les 3 premières valeurs puis il part en vadrouille dans l'univers du segfault:
    [...]
    -------------------------------
    note: 7.706422 / 10
    -------------------------------
    -------------------------------
    calcul de notre pour le 2eme produit, cout=2.050000 max=2.490000 min=1.400000
    Erreur de segmentation
    Je ne trouve pas ce qui cloche.

    C'est un programme fait à l'arrache pour dépanner, il doit marcher demain soir au plus tard. Je suis pas loin d'avoir ce que je veux, mais ... j'y suis pas

    Merci d'avance.
    Toutes les vertus des hommes se perdent dans l’intérêt comme les fleuves se perdent dans la mer.
    N'oubliez pas de consulter les FAQ Linux et les cours et tutoriels Linux

  2. #2
    Modérateur
    Avatar de ggnore
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    2 472
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 2 472
    Points : 4 029
    Points
    4 029
    Par défaut
    hum, allocation d'un tableau d'entier alors que c'est un tableau de float

    mais ça ne résout rien
    Toutes les vertus des hommes se perdent dans l’intérêt comme les fleuves se perdent dans la mer.
    N'oubliez pas de consulter les FAQ Linux et les cours et tutoriels Linux

  3. #3
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Citation Envoyé par ggnore
    hum, allocation d'un tableau d'entier alors que c'est un tableau de float

    mais ça ne résout rien
    Arf, je vois qu'il est temps de te rappeler les bonnes manières : Bien utiliser malloc()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tableau_resultat = malloc ( sizeof(*tableau_resultat) * nb_ligne)
    Comme ça plus de problème

    Allez on va dire que c'est la remise en route

  4. #4
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Deux erreurs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    tableau_resultat = malloc ( sizeof(int) * nb_ligne))
    devrait être:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    tableau_resultat = malloc ( sizeof(float) * nb_ligne))
    EDITION: en effet, ceci aurait éviter des ennuis...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    tableau_resultat = malloc ( sizeof(*tableau_resultat) * nb_ligne))
    Ensuite:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *tableau_resultat[prod_traite]
    Est faux puisque ton tableau n'est qu'un tableau de flottant... Ce que tu voudrais faire c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (*tableau_resultat)[prod_traite]
    Mais cela ne sert à rien, ton prototype pourrait simplement être:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int traitement (float * tableau_resultat, int nb_ligne)
    Et tes affectations seraient donc:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tableau_resultat[prod_traite]
    Tu n'aurais pas eu d'erreurs à ce moment là...

    Jc

  5. #5
    Modérateur
    Avatar de ggnore
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    2 472
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 2 472
    Points : 4 029
    Points
    4 029
    Par défaut
    merci beaucoup
    C'est loin de fonctionner correctement, mais là ça doit être algorithmique.

    Je voulais abosulement passer ce tableau par adresse, alors que ça n'a rien de nécessaire.

    to be continued
    Toutes les vertus des hommes se perdent dans l’intérêt comme les fleuves se perdent dans la mer.
    N'oubliez pas de consulter les FAQ Linux et les cours et tutoriels Linux

  6. #6
    Modérateur
    Avatar de ggnore
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    2 472
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 2 472
    Points : 4 029
    Points
    4 029
    Par défaut
    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
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define debug1
     
    void erreur(char * msg){
            printf ("\n Erreur : %s\n", msg);
    }
     
    void affiche(char * msg){
    #ifdef debug
            printf ("\n--\n%s\n--",msg);
    #endif
     
    }
     
    int     lire_ligne( int * lot_n, float * cout_n, int * ligne_lue)
    {
            char * dummy;
            char chaine[128];
            char tmp[64];
     
            char * lot_c;
            char * cout_c;
     
            if(fgets(chaine, 128, stdin) == NULL){
                    erreur("fgets");
                    return -1;
            }
     
            sprintf(tmp,"Lecture ligne n°%d", *ligne_lue);
            affiche(tmp);
     
            lot_c = strtok (chaine,":");
            cout_c = strtok (NULL, ":");
     
            *lot_n = strtol ( lot_c, &dummy, 10);
            if( (*cout_n = strtod(cout_c, &dummy)) == 0){
                    sprintf(tmp, "valeur vaut 0, ligne %d ", *ligne_lue);
                    affiche(tmp);
     
            }
     
     
            (*ligne_lue)++;
     
            return 0;
    }
     
    int traitement (float * tableau_resultat, int nb_ligne){
     
            char tmp[128];
            float chaine_cout[1024];
     
     
            int lot_courant=0;
            int nb_prod_par_lot=0;
            int nb_prod_tot=0;
            int ligne_faite=0, ligne_lue=0;
            int prod_traite=0;
     
            float max, min;
            float cout_lot;
     
            float test;
     
            int lot_n=-1;
            float cout_n;
     
            // tant qu'on n'a pas parcouru et traite tous les produits (et donc tous les lots)
            while (ligne_faite < nb_ligne){
                    cout_lot = 0;
     
                    if (lot_n != lot_courant){
                            if (lire_ligne(&lot_n, &cout_n, &ligne_lue) == -1) return -1;
                            sprintf(tmp, "amorce car (lot_n %d) != (lot_courant %d)", lot_n, lot_courant);
                            affiche(tmp);
                    }
     
                    sprintf(tmp,"\n%d. =>lot: %d >cout: %f ¹", ligne_lue, lot_n, cout_n);
                    affiche(tmp);
     
                    lot_courant = lot_n;
                    max = min = cout_n;
                    chaine_cout[ligne_lue-1] = cout_n;
                    cout_lot += cout_n;
     
                    nb_prod_par_lot++;
     
                    // tant qu'on n'a pas parcouru tous les produits d'un lot
                    while ( (lot_courant == lot_n) && (ligne_lue < nb_ligne) ){
                            sprintf(tmp, "while ( (lot_courant %d == lot_n %d ) && (ligne_lue %d  < nb_ligne %d) )",lot_courant,lot_n,ligne_lue,nb_ligne);
                            affiche(tmp);
                            if(lire_ligne(&lot_n, &cout_n, &ligne_lue) == -1) return -1;
     
                            sprintf(tmp,"\n%d. =>lot: %d >cout: %f ²", ligne_lue, lot_n, cout_n);
                                    affiche(tmp);
     
                            if (lot_courant != lot_n) {
                                    continue;
                            }
     
                            if (max<cout_n) max=cout_n;
                            if (min>cout_n) min=cout_n;
     
                            chaine_cout[ligne_lue-1]=cout_n;
     
                            nb_prod_par_lot++;
                            cout_lot+=cout_n;
                    }
     
                    // calcul des notes
                    for (prod_traite = 0 ; prod_traite < nb_prod_par_lot ; prod_traite++){
                            sprintf(tmp,"calcul note pour %deme produit, cout=%f max=%f min=%f", prod_traite, chaine_cout[ligne_faite], max, min);
                            affiche(tmp);
     
                            if (max==min) {
                                    tableau_resultat[ligne_faite] = 5;
                            }
                            // si le cout est minimum on a un 10
                            else if (chaine_cout[ligne_faite] == min){
     
                                    tableau_resultat[ligne_faite] = 10;
                            }
                            // si le cout est max, on a un 1
                            else if (chaine_cout[ligne_faite] == max){
     
                                    tableau_resultat[ligne_faite] = 1;
                            }
                            // sinon on calcule relativement
                            else {
                                    tableau_resultat[ligne_faite] = (float)(10 -  (10 * (chaine_cout[ligne_faite] - min)/(max-min)));
                            }
                            printf("%f\n",tableau_resultat[ligne_faite]);
     
                            ligne_faite++;
                    }
                    nb_prod_par_lot = 0;
                    lot_courant = lot_n;
     
            }
            return(0);
     
    }
     
    int main(int argc, char *argv[])
    {
            int nb_ligne=0;
            int curseur;
     
            char tmp[64];
            char * dummy;
            float * tableau_resultat;
     
            if (argc == 2){
                    sprintf (tmp,"argv[1]=%s", argv[1]);
                    affiche(tmp);
                    nb_ligne=strtol(argv[1], &dummy, 10);
                    sprintf(tmp, "nb_l=%d", nb_ligne);
                    affiche(tmp);
            }
            else {
                    sprintf(tmp,"arguments > besoin du nombre de ligne, argc=%d", argc);
                    erreur(tmp);
                    return -1;
            }
     
            if ( (tableau_resultat = (float*) malloc ( sizeof(*tableau_resultat) * nb_ligne)) == NULL ){
                    sprintf(tmp,"allocation tableau %d elements", nb_ligne);
                    erreur(tmp);
                    return -1;
            }
     
            sprintf(tmp,"allocation tableau %d elements", nb_ligne);
            affiche(tmp);
     
            traitement( tableau_resultat, nb_ligne);
     
            free(tableau_resultat);
     
            return 0;
    }
    J'ai encore un segfault quand je traite beaucoup de données.
    Comment puis détecter une erreur quand j'utilise strtod ? il se peut que je récupère un 0 comme valeur, donc ça n'est pas un bon test.
    Je n'ai pas bien compris avec le man strtod quoi faire pr détecter un erreur.
    Merci d'avance.
    Toutes les vertus des hommes se perdent dans l’intérêt comme les fleuves se perdent dans la mer.
    N'oubliez pas de consulter les FAQ Linux et les cours et tutoriels Linux

  7. #7
    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
    Au lieu de NULL, tu passes l'adresse d'un pointeur.

    Exemple:
    Si après l'appel, le caractère pointé est nul, c'est que la chaîne a été entièrement lue -->aucune erreur
    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.

  8. #8
    Modérateur
    Avatar de ggnore
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    2 472
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 2 472
    Points : 4 029
    Points
    4 029
    Par défaut
    Citation Envoyé par Médinoc
    Au lieu de NULL, tu passes l'adresse d'un pointeur.

    Exemple:
    Si après l'appel, le caractère pointé est nul, c'est que la chaîne a été entièrement lue -->aucune erreur
    Ok merci, j'ai rajouté ce test, mais je ne détecte aucune erreur.

    Je considère le problème comme résolu : après moultes tests, je me suis rendu compte que ça plantait systématiquement au 1025 éléments.
    C'est marrant, j'ai un tableau qui fait 1024 cases ...

    Bon c'était un programme fait à l'arrache.
    Maintenant c'est bon, je me suis mis 65536 éléments
    Toutes les vertus des hommes se perdent dans l’intérêt comme les fleuves se perdent dans la mer.
    N'oubliez pas de consulter les FAQ Linux et les cours et tutoriels Linux

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

Discussions similaires

  1. Dépassement du quotas maximal pour la longueur du tableau
    Par MaximeLeroy dans le forum Windows Communication Foundation
    Réponses: 5
    Dernier message: 18/07/2013, 16h06
  2. Dépassement de capacité Tableau dynamique VBA
    Par hehee dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 01/06/2013, 18h21
  3. Problème de dépassement de tableau
    Par scary dans le forum C
    Réponses: 4
    Dernier message: 10/01/2010, 16h16
  4. Dépassement de tableau
    Par infoblem67 dans le forum Débuter
    Réponses: 5
    Dernier message: 15/11/2008, 23h33
  5. Réponses: 3
    Dernier message: 11/09/2007, 18h20

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