Home > Software engineering >  Segmentation fault inc
Segmentation fault inc

Time:08-31

/*
https://stackoverflow.com/questions/53220084/proper-input-method-to-take-char-string-input-in-c/53221258#53221258

gcc array_struct_3.c &&./a.out

*/ 

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

#define ROW 5       /* if you need a constant, #define one (or more) */
#define COL 64

typedef struct student_t
{
    char name[COL];
    int score;
} student_t;

int student_t_cmp_score(const void *x, const void *y)
{
    struct student_t* const *ix = x; 
    struct student_t* const *iy = y; 
    return ((*ix)->score > (*iy)->score) - ((*ix)->score < (*iy)->score);
}
int main(void)
{
    int n = 0;
    
    // student_t student[ROW] = {{.name = ""}};
    student_t *student[ROW];

    puts("\n[note; press enter alone to end input]\n");
    (student[n]) = malloc(sizeof(struct student_t));
    
    for(;;){
        char buf[COL];
        fputs("Enter student name: ", stdout);

        if (!fgets(buf, sizeof buf, stdin)) /* read/validate line */
            break;
        if(*buf == '\n') /* check for empty line */
            break;

        /* parse line into name and score - validate! */

        if(sscanf(buf,"cs %d",student[n]->name, &student[n]->score) != 2)
        {
            fputs(" error: invalid input, conversion failed.\n",stderr);
            continue;
        }
        n  ;
        student[n] = malloc(sizeof(struct student_t));

        if(n== ROW){
            fputs("\narray full - input complete.\n", stdout);
            break;
        }
    }
    printf("sizeof student: %zu\n", sizeof *student);
    
    qsort(student, n, sizeof *student,student_t_cmp_score);
    
    for(int i = 0; i < n; i  )
        printf("%-16s =\n",student[i]->name, student[i]->score);
    return 0;
}

The above version will work. However, I try the following code then it's Segmentation fault. The line to make Segmentation fault is: qsort(&student, n, sizeof *student,student_t_cmp_score); .Since there is only 4 variable, so the only problem will be either &student or student_t_cmp_score for student_t_cmp_score, I just follow/copy other people code. Overall I don't know why it's Segmentation fault.

typedef struct student_t
{
    char name[COL];
    int score;
} student_t;

int student_t_cmp_score(const void *x, const void *y)
{
    struct student_t* const *ix = x; 
    struct student_t* const *iy = y; 
    return ((*ix)->score > (*iy)->score) - ((*ix)->score < (*iy)->score);
}
int main(void)
{
    int n = 0;
    
    student_t student[ROW] = {{.name = ""}};
    // student_t *student[ROW];

    puts("\n[note; press enter alone to end input]\n");
    // (student[n]) = malloc(sizeof(struct student_t));
    
    for(;;){
        char buf[COL];
        fputs("Enter student name: ", stdout);

        if (!fgets(buf, sizeof buf, stdin)) /* read/validate line */
            break;
        if(*buf == '\n') /* check for empty line */
            break;

        /* parse line into name and score - validate! */

        if(sscanf(buf,"cs %d",student[n].name, &student[n].score) != 2)
        {
            fputs(" error: invalid input, conversion failed.\n",stderr);
            continue;
        }
        n  ;
        // student[n] = malloc(sizeof(struct student_t));

        if(n== ROW){
            fputs("\narray full - input complete.\n", stdout);
            break;
        }
    }
    printf("sizeof student: %zu\n", sizeof *student);

    qsort(&student, n, sizeof *student,student_t_cmp_score);
    // qsort(student, n, sizeof *student,student_t_cmp_score);
    
    for(int i = 0; i < n; i  )
        printf("%-16s =\n",student[i].name, student[i].score);
    return 0;
}

I also tried use GDB via following command.

gdb ./a.out
(gdb) run
<segfault happens here>
(gdb) backtrace

error show in terminal:

sizeof student: 68

Program received signal SIGSEGV, Segmentation fault.
student_t_cmp_score (x=0x7fffffffdbe0, y=0x7fffffffdc24) at array_struct_3.c:22
warning: Source file is more recent than executable.
22      int student_t_cmp_score(const void *x, const void *y)
(gdb) backtrace
#0  student_t_cmp_score (x=0x7fffffffdbe0, y=0x7fffffffdc24) at array_struct_3.c:22
#1  0x00007ffff7dc6491 in msort_with_tmp (p=p@entry=0x7fffffffdb60, b=b@entry=0x7fffffffdab8,
    n=n@entry=2) at ./stdlib/msort.c:123
#2  0x00007ffff7dc63a5 in msort_with_tmp (n=2, b=0x7fffffffdab8, p=0x7fffffffdb60)
    at ./stdlib/msort.c:44
#3  msort_with_tmp (p=p@entry=0x7fffffffdb60, b=0x7fffffffdab8, n=n@entry=5) at ./stdlib/msort.c:52
#4  0x00007ffff7dc6992 in msort_with_tmp (n=5, b=<optimized out>, p=0x7fffffffdb60)
    at ./stdlib/msort.c:44
#5  __GI___qsort_r (b=<optimized out>, n=<optimized out>, s=68, cmp=<optimized out>, arg=0x0)
    at ./stdlib/msort.c:253
#6  0x0000555555555417 in main () at array_struct_3.c:60

CodePudding user response:

You changed from an array of pointers to a plain array. So your items are no longer pointers-to-struct, but struct items.

Change the callback function accordingly:

int student_t_cmp_score (const void *x, const void *y)
{
    const struct student_t* ix = x; 
    const struct student_t* iy = y; 
    return (ix->score > iy->score) - (ix->score < iy->score);
}
  •  Tags:  
  • c
  • Related