我的 readFile 中的分段错误

Segmentation Fault in my readFile

我正在创建一个程序,该程序将从具有下面提到的格式的文件中读取,并为每一行生成一个结构,其中包含相应的模型、引擎大小、成本和颜色。它似乎是 token = strtok(line, " "); 行的段错误在 while 循环中,此时我不太明白为什么。这确实读取了文件并读取了第一行,它打印出第一行就好了,但是在执行 strtok

时出现段错误
F150 5.4 26000 white
RAM1500 5.5 30000 orange
F150 5.6 27000 white
RAM1500 5.7 31000 orange
F150 5.8 28000 white
RAM1500 5.9 32000 orange
F150 5.3 29000 white
RAM1500 5.2 33000 orange

这是我正在构建的数组的结构

struct data{

    char *model;
    float engineSize;
    int cost;
    char *color;
};

这是读取文件和生成结构的程序代码

         void  readFile(int check){

    FILE *fp;
    int c;
    int count = 0;
    char *line = NULL;
    size_t len = 0;

    fp = fopen("hw3.data", "r");

    if(fp == NULL){

        printf("did not find file \n");
        exit(0);
    }


    while ((c = fgetc(fp)) != EOF){
        if(c == '\n'){
            count++;
        }

    }
    if (feof(fp)){

        rewind(fp);

        struct data *vehicles = malloc((sizeof(struct data))* count);


        int index = 0;
        char *token = NULL;

        //Program is seg faulting in this loop along the token = strtok();
        while (getline(&line, &len, fp)!= -1){



            token = strtok(line,  " ");




            vehicles[index].model = malloc(strlen(token) + 1);




            strcpy(vehicles[index].model, token);

            token = strtok(NULL, " ");
            vehicles[index].engineSize = atof(token);

            token = strtok(NULL, " ");
            vehicles[index].cost = atoi(token);

            token = strtok(NULL, " ");
            vehicles[index].color = malloc(strlen(token) + 1);
            strcpy(vehicles[index].color, token);

            free(line);
            line = NULL;
            len = 0;
            index++;


        }

        if(check == 1){

            bubbleSortFloats(vehicles, 0, count);

        }if(check == 2){

            bubbleSortFloats(vehicles, 1, count);

        }if(check == 3){

            bubbleSortInts(vehicles, 0, count);

        }if(check == 4){

            bubbleSortInts(vehicles, 1, count);

        }


        for(int z = 0; z < count; z++){


        free(&vehicles[z].model);
        vehicles[z].model = NULL;
        free(&vehicles[z].color);
        vehicles[z].color = NULL;
        free(&vehicles[z]);


        }

    }
}

这是我程序的其余代码,如果你想看的话

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

struct data{

    char *model;
    float engineSize;
    int cost;
    char *color;
};


void printStruct(struct data vehicles[], int check){


}


void bubbleSortInts(struct data vehicles[], int check)
{
   int i, j, n;



  // If check == 1 then ascending sort
  if(check == 1){

   for (i = 0; i < n-1; i++){     

       // Last i elements are already in place   
       for (j = 0; j < n-i-1; j++){


           if (vehicles[j].cost > vehicles[j+1].cost){

                struct data temp = vehicles[j];
                vehicles[j] = vehicles[j+1];
                vehicles[j+1] = temp; 

           }
        }
    }
  }
    // If check == 0 then decending sort
  if(check == 0){

    for (i = 0; i < n-1; i++){     

       // Last i elements are already in place   
       for (j = 0; j < n-i-1; j++){


           if (vehicles[j].engineSize < vehicles[j+1].engineSize){

                struct data temp = vehicles[j+1];
                vehicles[j+1] = vehicles[j];
                vehicles[j] = temp; 

           }
        }
    }
  }
    printStruct(vehicles, n);
    return;          
}

void bubbleSortFloats(struct data vehicles[], int check)
{
   int i, j, n;


  // If check == 1 then ascending sort
  if(check == 1){

   for (i = 0; i < n-1; i++){     

       // Last i elements are already in place   
       for (j = 0; j < n-i-1; j++){


           if (vehicles[j].engineSize > vehicles[j+1].engineSize){

                struct data temp = vehicles[j];
                vehicles[j] = vehicles[j+1];
                vehicles[j+1] = temp; 

           }
        }
    }
  }
    // If check == 0 then decending sort
  if(check == 0){

    for (i = 0; i < n-1; i++){     

       // Last i elements are already in place   
       for (j = 0; j < n-i-1; j++){


           if (vehicles[j].engineSize < vehicles[j+1].engineSize){

                struct data temp = vehicles[j+1];
                vehicles[j+1] = vehicles[j];
                vehicles[j] = temp; 

           }
        }
    }
  }
    printStruct(vehicles, n); 

}

主要

 int main(){

    int check = 1;
    int input, n;

    while (check == 1){

        printf("Enter a value corresponding to a option on the menu below\n\n");

        printf("1. Sort data by the float value & print high to low\n");
        printf("2. Sort data by the float value & print low to high\n");
        printf("3. Sort data by the int value & print high to low\n");
        printf("4. Sort data by the int value & print low to high\n");
        printf("5. Exit\n\n");

        printf("Enter a value corresponding to the above menu\n");
        scanf("%d", &input);





        if(input == 1 || input == 2 || input == 3 || input == 4 || input == 5){

            if (input == 5){

                exit(0);

            }if (input == 1){

                //sort float high to low
                //bubbleSortFloats(vehicles[], 0);
                readFile(1);

            }if (input == 2){

                //sort float low to high
                //bubbleSortFloats(vehicles[], 1);
                readFile(2);

            }if (input == 3){


                //sort int value high to low
                //bubbleSortInts(vehicles[], 0);
                readFile(3);


            }if (input == 4){

                //sort int value low to high
                //bubbleSortInts(vehicles[], 1);
                readFile(4);

            }

        }else{

            printf("Enter a correct value for the menus above\n\n" );
        }



    }

}
struct data *vehicles = malloc((sizeof(struct data))* count);
int count2 = 0;
..
while (getline(&line, &len, fp)!= -1){
  token = strtok(line,  " ");
  ...
  strcpy(vehicles[count].model, token);

最后一个 strcpy 溢出 vehicles 缓冲区。您可能打算使用不同的索引:

 strcpy(vehicles[count2].model, token);

count2(根本不是计数)重命名为 index 可能也有帮助。您还需要在循环中的某处增加该索引。

一般来说,使用适当的工具很容易找到这些类型的错误。在 Linux 上,您可以使用 valgrind or address sanitizer.

看到你只使用了我的一些建议,我决定写一个 实际工作的版本(你也一直在为这段代码努力工作)。

只有一件事是错误的:您的 bubbleSortInts 用于降序排序 不正确,您比较的是 engineSize 而不是 cost,我已修复。

我重写了处理菜单和输入的部分代码。拿一个 查看文件如何只读一次。一旦它在内存中,你不需要 再次读取文件,所以可以先读取文件再进入菜单 模式。查看 free_vehicles 函数,它向您展示了如何释放 记忆。我使用 calloc 来获取数组的内存。 calloc有好处 它将分配的内存设置为 0。这对于初始化结构非常有用 指针必须是免费的。你可以释放整个事情 free_vehicles 甚至在整个数组已满之前,例如当 strtok returnsNULL。在这种情况的错误处理中,可以简单的做

if(token == NULL)
{
    free_vehicles(vehicles, *len);
    return NULL;
}

free 将是正确的,因为 free(NULL) 是允许的。 我省略了 strtok 的检查以及 modelcolor 的副本, 所以你可以添加这个检查。

下面的代码你可以直接拿来,我编译测试了一下(见 下面输出)。所以你可以使用这段代码作为你以后的代码库 改进。

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


struct data {
    char *model;
    float engineSize;
    int cost;
    char *color;
};

void print_vehicles(struct data *vehicles, size_t len)
{
    if(vehicles == NULL)
        return;

    for(size_t i = 0; i < len; ++i)
    {
        printf("Vehicle %lu: %-10s engine size: %-4f, price: %-4d USD, color: %s\n",
                i+1, vehicles[i].model, vehicles[i].engineSize, vehicles[i].cost,
                vehicles[i].color);
    }
    puts("");
}

struct data *readFile(size_t *len)
{
    if(len == NULL)
        return NULL;

    struct data *vehicles = NULL;
    *len = 0;

    FILE *fp;
    int c;

    fp = fopen("hw3.data", "r");

    if(fp == NULL){

        fprintf(stderr, "could not open file\n");
        return NULL;
    }


    // finding out the number of lines
    while ((c = fgetc(fp)) != EOF){
        if(c == '\n')
            (*len)++;
    }

    if (feof(fp)){

        rewind(fp);

        // allocate memory
        vehicles = calloc(*len, sizeof *vehicles);

        int index = 0;
        char *token = NULL;
        char *line = NULL;
        size_t line_length = 0;
        const char *delim = " \n"; // getting rid of \n as well

        //Program is seg faulting in this loop along the token = strtok();
        while (getline(&line, &line_length, fp)!= -1){

            token = strtok(line, delim);

            vehicles[index].model = malloc(strlen(token) + 1);
            strcpy(vehicles[index].model, token);

            token = strtok(NULL, delim);
            vehicles[index].engineSize = atof(token);

            token = strtok(NULL, delim);
            vehicles[index].cost = atoi(token);

            token = strtok(NULL, delim);
            vehicles[index].color = malloc(strlen(token) + 1);
            strcpy(vehicles[index].color, token);

            free(line);
            line = NULL;
            line_length = 0;
            index++;
        }

        // freeing the last line
        free(line);
    }

    fclose(fp);
    return vehicles;
}

void free_vehicles(struct data *vehicles, size_t len)
{
    if(vehicles == NULL)
        return;

    for(size_t i = 0; i < len; ++i)
    {
        free(vehicles[i].model);
        free(vehicles[i].color);
    }

    free(vehicles);
}

void bubbleSortInts(struct data *vehicles, size_t len, int check)
{
   int i, j, n = len;



  // If check == 1 then ascending sort
  if(check == 1){

   for (i = 0; i < n-1; i++){     

       // Last i elements are already in place   
       for (j = 0; j < n-i-1; j++){


           if (vehicles[j].cost > vehicles[j+1].cost){

                struct data temp = vehicles[j];
                vehicles[j] = vehicles[j+1];
                vehicles[j+1] = temp; 

           }
        }
    }
  }
    // If check == 0 then decending sort
  if(check == 0){

    for (i = 0; i < n-1; i++){     

       // Last i elements are already in place   
       for (j = 0; j < n-i-1; j++){


           if (vehicles[j].cost < vehicles[j+1].cost){

                struct data temp = vehicles[j+1];
                vehicles[j+1] = vehicles[j];
                vehicles[j] = temp; 

           }
        }
    }
  }
    return;          
}


void bubbleSortFloats(struct data *vehicles, size_t len, int check)
{
   int i, j, n = len;


  // If check == 1 then ascending sort
  if(check == 1){

   for (i = 0; i < n-1; i++){     

       // Last i elements are already in place   
       for (j = 0; j < n-i-1; j++){


           if (vehicles[j].engineSize > vehicles[j+1].engineSize){

                struct data temp = vehicles[j];
                vehicles[j] = vehicles[j+1];
                vehicles[j+1] = temp; 

           }
        }
    }
  }
    // If check == 0 then decending sort
  if(check == 0){

    for (i = 0; i < n-1; i++){     

       // Last i elements are already in place   
       for (j = 0; j < n-i-1; j++){


           if (vehicles[j].engineSize < vehicles[j+1].engineSize){

                struct data temp = vehicles[j+1];
                vehicles[j+1] = vehicles[j];
                vehicles[j] = temp; 

           }
        }
    }
  }

}


int read_menu(void)
{
    int input;
    printf("Enter a value corresponding to a option on the menu below\n\n");

    printf("1. Sort data by the float value & print high to low\n");
    printf("2. Sort data by the float value & print low to high\n");
    printf("3. Sort data by the int value & print high to low\n");
    printf("4. Sort data by the int value & print low to high\n");
    printf("5. Exit\n\n");

    printf("Enter a value corresponding to the above menu\n");

    char line[1024];
    if(fgets(line, sizeof line, stdin))
    {
        char *tmp;
        line[strcspn(line, "\n")] = 0;
        input = strtol(line, &tmp, 0);

        if(*tmp == 0)
            return input;
    }

    return -1;
}

int main(void)
{
    struct data *vehicles = NULL;
    size_t num_of_vehicles = 0;

    int input = -1;

    // read data only once
    vehicles = readFile(&num_of_vehicles);

    if(vehicles == NULL)
    {
        fprintf(stderr, "Not enough memory\n");
        return 1;
    }

    while((input = read_menu()) != 5)
    {
        switch(input)
        {
            case 1:
                bubbleSortFloats(vehicles, num_of_vehicles, 0);
                break;
            case 2:
                bubbleSortFloats(vehicles, num_of_vehicles, 1);
                break;
            case 3:
                bubbleSortInts(vehicles, num_of_vehicles, 0);
                break;
            case 4:
                bubbleSortInts(vehicles, num_of_vehicles, 1);
                break;
            default:
                continue;
        }

        print_vehicles(vehicles, num_of_vehicles);
    }

    // free the data
    free_vehicles(vehicles, num_of_vehicles);

    return 0;
}

这是输出:

$ valgrind ./car-db
==12625== Memcheck, a memory error detector
==12625== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==12625== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==12625== Command: ./car-db
==12625== 
Enter a value corresponding to a option on the menu below

1. Sort data by the float value & print high to low
2. Sort data by the float value & print low to high
3. Sort data by the int value & print high to low
4. Sort data by the int value & print low to high
5. Exit

Enter a value corresponding to the above menu
1
Vehicle 1: RAM1500    engine size: 5.900000, price: 32000 USD, color: orange
Vehicle 2: F150       engine size: 5.800000, price: 28000 USD, color: white
Vehicle 3: RAM1500    engine size: 5.700000, price: 31000 USD, color: orange
Vehicle 4: F150       engine size: 5.600000, price: 27000 USD, color: white
Vehicle 5: RAM1500    engine size: 5.500000, price: 30000 USD, color: orange
Vehicle 6: F150       engine size: 5.400000, price: 26000 USD, color: white
Vehicle 7: F150       engine size: 5.300000, price: 29000 USD, color: white
Vehicle 8: RAM1500    engine size: 5.200000, price: 33000 USD, color: orange

Enter a value corresponding to a option on the menu below

1. Sort data by the float value & print high to low
2. Sort data by the float value & print low to high
3. Sort data by the int value & print high to low
4. Sort data by the int value & print low to high
5. Exit

Enter a value corresponding to the above menu
2
Vehicle 1: RAM1500    engine size: 5.200000, price: 33000 USD, color: orange
Vehicle 2: F150       engine size: 5.300000, price: 29000 USD, color: white
Vehicle 3: F150       engine size: 5.400000, price: 26000 USD, color: white
Vehicle 4: RAM1500    engine size: 5.500000, price: 30000 USD, color: orange
Vehicle 5: F150       engine size: 5.600000, price: 27000 USD, color: white
Vehicle 6: RAM1500    engine size: 5.700000, price: 31000 USD, color: orange
Vehicle 7: F150       engine size: 5.800000, price: 28000 USD, color: white
Vehicle 8: RAM1500    engine size: 5.900000, price: 32000 USD, color: orange

Enter a value corresponding to a option on the menu below

1. Sort data by the float value & print high to low
2. Sort data by the float value & print low to high
3. Sort data by the int value & print high to low
4. Sort data by the int value & print low to high
5. Exit

Enter a value corresponding to the above menu
3
Vehicle 1: RAM1500    engine size: 5.200000, price: 33000 USD, color: orange
Vehicle 2: RAM1500    engine size: 5.900000, price: 32000 USD, color: orange
Vehicle 3: RAM1500    engine size: 5.700000, price: 31000 USD, color: orange
Vehicle 4: RAM1500    engine size: 5.500000, price: 30000 USD, color: orange
Vehicle 5: F150       engine size: 5.300000, price: 29000 USD, color: white
Vehicle 6: F150       engine size: 5.800000, price: 28000 USD, color: white
Vehicle 7: F150       engine size: 5.600000, price: 27000 USD, color: white
Vehicle 8: F150       engine size: 5.400000, price: 26000 USD, color: white

Enter a value corresponding to a option on the menu below

1. Sort data by the float value & print high to low
2. Sort data by the float value & print low to high
3. Sort data by the int value & print high to low
4. Sort data by the int value & print low to high
5. Exit

Enter a value corresponding to the above menu
4
Vehicle 1: F150       engine size: 5.400000, price: 26000 USD, color: white
Vehicle 2: F150       engine size: 5.600000, price: 27000 USD, color: white
Vehicle 3: F150       engine size: 5.800000, price: 28000 USD, color: white
Vehicle 4: F150       engine size: 5.300000, price: 29000 USD, color: white
Vehicle 5: RAM1500    engine size: 5.500000, price: 30000 USD, color: orange
Vehicle 6: RAM1500    engine size: 5.700000, price: 31000 USD, color: orange
Vehicle 7: RAM1500    engine size: 5.900000, price: 32000 USD, color: orange
Vehicle 8: RAM1500    engine size: 5.200000, price: 33000 USD, color: orange

Enter a value corresponding to a option on the menu below

1. Sort data by the float value & print high to low
2. Sort data by the float value & print low to high
3. Sort data by the int value & print high to low
4. Sort data by the int value & print low to high
5. Exit

Enter a value corresponding to the above menu
5
==12625== 
==12625== HEAP SUMMARY:
==12625==     in use at exit: 0 bytes in 0 blocks
==12625==   total heap usage: 30 allocs, 30 frees, 8,072 bytes allocated
==12625== 
==12625== All heap blocks were freed -- no leaks are possible
==12625== 
==12625== For counts of detected and suppressed errors, rerun with: -v
==12625== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)