简体   繁体   中英

Why am I getting segmentation fault while mallocing?

I have the following code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tournament.h"
Player * draftPlayers(char * filename, int team, int num_players){
Player *player[10];
int it;
for(it=0;it<10;it++)
{
    player[it]=malloc(sizeof(Player));

}
FILE *fp;
char *line = NULL;
size_t len = 0;
ssize_t read;
char *token[100];
int  i=0,j,k;
fp = fopen(filename, "r");
while (getline(&line, &len, fp) != -1) {
    player[it]->first=malloc(sizeof(char)*50);
    player[it]->last=malloc(sizeof(char)*50);
    j=0;
    token[0] = strtok(line, ",");
    while(token[j] != NULL ) {
        j++;
        token[j] = strtok(NULL, ",");
    }

    if(team==atoi(token[0])){
        player[i]->team=atoi(token[0]);
        printf("%s\n","Here3");
        strcpy(player[i]->first,token[1]);
        printf("%s\n","Here3");
        strcpy(player[i]->last,token[2]);
        printf("%s\n","Here3");
        player[i]->number=atoi(token[3]);
        printf("%s\n","Here3");
        player[i]->offensive=atoi(token[4]);
        printf("%s\n","Here3");
        player[i]->defensive=atoi(token[5]);    
        printf("%s\n","Here3");
    }

    i++;    
}

printf("%s\n","Here4");
fclose(fp);
printf("%s\n","Here5");
if (line){
    printf("%s\n","Here6");
    free(line);}
printf("%s\n","Here7");
return player;

}

I am getting the output:

Here3
Here3
Here3
Here3
Here3
Here3
Here4
Here5
Here6
Here7
Here3
Here3
Here3
Here3
Here3
Here3
Segmentation fault

Please let me know my mistake. I have tried everything but I am unable to get the root of error. I want to know what I am doing wrong here. I am unable to get why there is a segmentation fault.

I am calling main as: Basically I am calling the same function as above.

#include"tournament.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
  Player * draft = draftPlayers("players.dat", 1, 10);
}

The struct that I have implemented is:

Tournament.h:

typedef struct {
  int offensive;
  int defensive;
  int number;
  int team;
  char * first;
  char * last;
}Player;

players.dat:

0,Mei,Fellgatt,24,8,2
1,Richmound,Beazley,45,6,7
2,Gunther,Fackney,73,6,7
3,Stewart,Frowing,19,3,3
4,Sallee,Cuffley,70,2,4
5,Axel,Stollwerk,73,7,2
6,Othilie,Grigoliis,28,8,1
7,Igor,Claffey,28,8,3
8,Bruce,Schruur,73,5,2
9,Clovis,Wynes,59,8,4
10,Silvie,Thiolier,5,4,5
11,Maxie,Treher,57,6,6
12,Margette,Wraighte,44,8,2
13,Chryste,Byrnes,41,10,3
14,Ulysses,Sturmey,68,9,7
15,Woodman,Powrie,81,4,4
16,Zitella,Reddel,14,6,4
17,Bronny,McMearty,42,2,5
18,Jewel,Cheyney,14,2,4
19,Adelaida,Gunney,44,6,2
20,Adrienne,O'Looney,21,5,6
21,Branden,Wilcott,27,7,5
22,Etta,Nuth,41,8,2
23,Karney,Lightbowne,80,3,6
24,Pierson,Crippell,6,1,4
25,Lutero,Filchagin,26,3,7
26,Roth,Ferrierio,66,5,1
27,Gothart,Thickens,16,1,4
28,Dwain,Josuweit,4,5,2
29,Nanice,Eady,47,2,6
30,Zahara,Ousley,79,10,4
31,Nichols,Earle,7,8,6
0,Jodee,Sharple,42,2,3
1,Cordy,Tuckwood,29,6,1
2,Jillian,Neligan,22,9,3
3,Shirlene,Wrought,23,4,4
4,Shoshana,Wais,14,7,2
5,Julissa,Edinburough,26,8,3
6,Gerome,Hallbord,2,7,5
7,Vere,Riste,7,1,3
8,Dexter,Gecke,3,3,5
9,Jacintha,Cessford,96,3,1
10,Kerry,Cramphorn,1,2,6
11,L;urette,McCluskey,37,6,2
12,Birch,Jagoe,37,6,2
13,Lenore,Norvel,55,1,4
14,Eilis,Klink,88,3,4
15,Neil,Darrel,37,1,5
16,Imelda,Donner,26,7,4
17,Alexandro,Kilbee,10,7,6
18,Gram,Tregunna,28,10,7
19,Jdavie,Bampford,26,4,4
20,Robyn,Spinola,43,9,5
21,Yance,Cochern,16,7,6
22,Rogers,Blyden,15,5,3
23,Jerrilee,Tremlett,1,2,3
24,Nickie,Winsome,14,4,7
25,Andrew,Duetsche,63,4,2
26,Dewey,Mitten,6,2,1
27,Aldon,Dunkirk,43,4,3
28,Curtice,Egginson,54,3,1
29,Carly,Loisi,98,7,4
30,Chrissie,Keppe,1,5,6
31,Jenny,Harbidge,81,2,5

As pointed out to you in your comments, you have some errors in yor code:

  • You return the address of a local array. This is a array of poiters. You allocate to these pointers, but the array itself will go out of scope once you leave the function (and the allocated memory will be leaked). Also player is a Player ** after decaying into a pointer, ot a Player * , which is the return type of the function.
  • You confuse various indices in your loop.
  • Your allocatios are premature. For example, you don't need to allocate memory for all ten players when you don't know yet how many there are. Allocating 50 chars because "that's probably enough" is another case: Allocate according to string length when you copy the string. (The non-standard function strdup does this for you.)

Your function should read all players of a certain team from a file into a list of players. The calling function needs to see the array and how many elements there are in that array.

One way to do that is to return the allocated array of players and alter the number of players via a pointer. The caller must free the memory (and the memory for the first and last names) after use. This function should re-allocate the array before appending another player.)

Here's a program that does this:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Player Player;

struct Player {
    int team;
    char *first;
    char *last;
    int number;
    int offensive;
    int defensive;
};

Player *draftPlayers(char *filename, int team, int *nplayer)
{
    Player *player = NULL;

    FILE *fp;
    char *line = NULL;
    size_t len = 0;

    fp = fopen(filename, "r");

    *nplayer = 0;

    while (getline(&line, &len, fp) != -1) {
        char *tk;
        char *token[6];
        int j = 0;

        tk = strtok(line, ",");
        while (tk && j < 6) {
            token[j++] = tk;
            tk = strtok(NULL, ",");
        }

        if (j == 6 && team == atoi(token[0])) {
            player = realloc(player, (*nplayer + 1) * sizeof(*player));

            player[*nplayer].team = atoi(token[0]);
            player[*nplayer].first = strdup(token[1]);
            player[*nplayer].last = strdup(token[2]);
            player[*nplayer].number = atoi(token[3]);
            player[*nplayer].offensive = atoi(token[4]);
            player[*nplayer].defensive = atoi(token[5]);
            (*nplayer)++;
        }
    }

    fclose(fp);
    free(line);

    return player;
}

int main()
{
    int t;

    for (t = 1; t < 36; t++) {
        int n;
        Player *player = draftPlayers("kk", t, &n);

        if (n) {
            int i;

            printf("Team %d\n", t);

            for (i = 0; i < n; i++) {
                Player *p = player + i;

                printf("%d: %s %s (%d, %d, %d)\n",
                    i + 1, p->first, p->last,
                    p->number, p->offensive,p->defensive);

                free(p->first);
                free(p->last);
            }

            free(player);
            puts("");
        }        
    }

    return 0;
}

(This isn't ideal, but I've tried to be as close to your original function as possible. In the real code, all calls to fopen and realloc should have proper error checking, of course.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM