Thread: Why am I getting a segmentation fault?

  1. #1
    Registered User
    Join Date
    Nov 2012
    Posts
    51

    Why am I getting a segmentation fault?

    Hello fellow C programmers. I am trying to write a program for homework and am having trouble when creating the basic foundation for this assignment. When I try to compile I get these errors:

    Code:
    j = 0
    student[0]->first_name = SAM
    student[0]->last_name =  MALONE
    student[0]->month = MAY
    student[0]->day = 3
    student[0]->year = 1961
    j = 1
    Segmentation fault: 11
    First, I need to use a struct, so there is no way around that. My logic is that I need to increase the number in the bracket attached to student so that further down the road in my program I can compare the students (eg. Without the number in the bracket, I can't think of a way to compare them). Can anyone guide me on this seg fault? I tried to debug by printing out `j` and it looks as if it makes one full loop without trouble and then it crashes when it tries to increase `student[0]` to `student[1]`
    Any help would be greatly appreciated!

    Code:
    # include <stdio.h>
    # include <stdlib.h>
    # include <string.h>
    
    
    # define MAX_CHARS_IN_NAME 30
    
    
    typedef struct
    {
        char *first_name;
        char *last_name;
        char month[10];
        int day;
        int year;
    } person;
    
    
    int main()
    {
        // Create a file pointer and open the file
        FILE *ifp = fopen("birthday.txt", "r");
    
    
        // Test to see if the file opens
        if (!ifp)
        {
            printf("The file is unable to open!\n");
            return -1;
        }
    
    
        // Create variables for the number of classes, number of students in the class, birthday month/day/year, number of queried students, queried students
        int i, num_classes, num_students, num_of_queried;
        char queried_student;
    
    
        // Read in the number of classes. PROPERLY READ IN (TESTED)
        fscanf(ifp, "%d", &num_classes);
    
    
        // Read in the number of students in the class. PROPERLY READ IN (TESTED)
        fscanf(ifp, "%d", &num_students);
    
    
        // Allocating space for the students in the classroom
        person *student = malloc(sizeof(person));
        student->first_name = malloc(sizeof(char) * MAX_CHARS_IN_NAME);
        student->last_name = malloc(sizeof(char) * MAX_CHARS_IN_NAME);
    
    
        /*
        // Allocating space for the queried student
        person *queried_student = malloc(sizeof(person));
        queried_student->first_name = malloc(sizeof(char) *MAX_CHARS_IN_NAME);
        queried_student->last_name = malloc(sizeof(char) *MAX_CHARS_IN_NAME);
        */
        
        // Loop through the text file
        for (i=0; i< num_classes; i++)
        {
            int j;
    
    
            for (j=0; j< num_students; j++)
            {
    
    
                printf("j = %d\n", j);
    
    
                // Scan in the student's first name
                fscanf(ifp, "%s", student[j].first_name);
                printf("student[%d]->first_name = %s\n", j, student->first_name);
                
                // Scan in the student's last name
                fscanf(ifp, "%s", student[j].last_name);
                printf("student[%d]->last_name =  %s\n", j, student->last_name);
    
    
                // Scan in the student's birth month
                fscanf(ifp, "%s", student[j].month);
                printf("student[%d]->month = %s\n", j, student->month);
    
    
                // Scan in the student's birth day
                fscanf(ifp, "%d", &student[j].day);
                printf("student[%d]->day = %d\n", j, student->day);
                
                // Scan in the student's birth year
                fscanf(ifp, "%d", &student[j].year);
                printf("student[%d]->year = %d\n", j, student->year);
    
    
                // Scan in the number of queried students
                //fscanf(ifp, "%d", &num_of_queried);
            
                /* int k;
    
    
                for (k=0; k< num_of_queried; k++)
                {
    
    
                } */
    
    
            }
            
            
        }
    
    
    
    
        // Sort the list in order of birthday, IGNORING THE YEAR!!!
    
    
        // print output
    
    
    
    
        fclose(ifp);
        
        return 0;
    }

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    You have made a basic error.
    Code:
        // Allocating space for the students in the classroom
        person *student = malloc(sizeof(person));
        student->first_name = malloc(sizeof(char) * MAX_CHARS_IN_NAME);
        student->last_name = malloc(sizeof(char) * MAX_CHARS_IN_NAME);
    
        /*
        // Allocating space for the queried student
        person *queried_student = malloc(sizeof(person));
        queried_student->first_name = malloc(sizeof(char) *MAX_CHARS_IN_NAME);
        queried_student->last_name = malloc(sizeof(char) *MAX_CHARS_IN_NAME);
        */
    The problem is, though the comments say that you have a different intent, the two pieces of code both allocate one struct. So when you follow your plan and increment the number betwixt the brackets, you would be dereferencing student[1] at some point. The variable student[1] does not have any space. This causes the Segmentation fault.

    Allocating arrays in C is somewhat difficult. You do rely on malloc to return memory but you can request more than one thing at a time.
    Code:
    person *student = malloc ( sizeof ( person ) * num_students );
    Assuming the pointer student is not NULL, the pointer is allocated, and you can access up to and including num_students - 1.

    The memory should be freed when you are done with it as well. You should call free() for as many pointers as you allocate with malloc() eventually.

  3. #3
    Registered User
    Join Date
    Nov 2011
    Location
    Saratoga, California, USA
    Posts
    334
    Why do you think you can treat student as an array of structs
    Code:
    fscanf(ifp, "%s", student[j].first_name);
    when you pointed it to an allocation for a single struct?
    Code:
    person *student = malloc(sizeof(person));
    If you want an array, you need to create an array. Hint: What are you going to do with num_students?

  4. #4
    Registered User
    Join Date
    Nov 2012
    Posts
    51
    I multiplied the person struct by num_students but am still getting the seg fault

  5. #5
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by C0__0D View Post
    I multiplied the person struct by num_students but am still getting the seg fault
    And what about "first_name" and "last_name"? Every element of "student" is a struct which contains two char pointers, thus you need to allocate memory for each char pointer too.

    Bye, Andreas

  6. #6
    Registered User
    Join Date
    Nov 2012
    Posts
    51
    I took everyones advice and attempted to malloc enough space for the number of students:
    Code:
    
    
    
    # include <stdio.h>
    # include <stdlib.h>
    # include <string.h>
    
    
    # define MAX_CHARS_IN_NAME 30
    
    
    typedef struct
    {
        char *first_name;
        char *last_name;
        char month[10];
        int day;
        int year;
    } person;
    
    
    int main()
    {
        // Create a file pointer and open the file
        FILE *ifp = fopen("birthday.txt", "r");
    
    
        // Test to see if the file opens
        if (!ifp)
        {
            printf("The file is unable to open!\n");
            return -1;
        }
    
    
        // Create variables for the number of classes, number of students in the class, birthday month/day/year, number of queried students, queried students
        int i, num_classes, num_students, num_of_queried;
        char queried_student;
    
    
        // Read in the number of classes. PROPERLY READ IN (TESTED)
        fscanf(ifp, "%d", &num_classes);
    
    
        // Read in the number of students in the class. PROPERLY READ IN (TESTED)
        fscanf(ifp, "%d", &num_students);
    
    
        // Allocating space for the students in the classroom
        person *student = malloc(sizeof(person)*num_students);
        student->first_name = malloc(sizeof((char) * MAX_CHARS_IN_NAME)*num_students);
        student->last_name = malloc(sizeof((char) * MAX_CHARS_IN_NAME)*num_students);
    
    
        /*
        // Allocating space for the queried student
        person *queried_student = malloc(sizeof(person));
        queried_student->first_name = malloc(sizeof(char) *MAX_CHARS_IN_NAME);
        queried_student->last_name = malloc(sizeof(char) *MAX_CHARS_IN_NAME);
        */
        
        // Loop through the text file
        for (i=0; i< num_classes; i++)
        {
            int j;
    
    
            for (j=0; j< num_students; j++)
            {
    
    
                printf("j = %d\n", j);
    
    
                // Scan in the student's first name
                fscanf(ifp, "%s", student[j].first_name);
                printf("student[%d]->first_name = %s\n", j, student->first_name);
                
                // Scan in the student's last name
                fscanf(ifp, "%s", student[j].last_name);
                printf("student[%d]->last_name =  %s\n", j, student->last_name);
    
    
                // Scan in the student's birth month
                fscanf(ifp, "%s", student[j].month);
                printf("student[%d]->month = %s\n", j, student->month);
    
    
                // Scan in the student's birth day
                fscanf(ifp, "%d", &student[j].day);
                printf("student[%d]->day = %d\n", j, student->day);
                
                // Scan in the student's birth year
                fscanf(ifp, "%d", &student[j].year);
                printf("student[%d]->year = %d\n", j, student->year);
    
    
                // Scan in the number of queried students
                //fscanf(ifp, "%d", &num_of_queried);
            
                /* int k;
    
    
                for (k=0; k< num_of_queried; k++)
                {
    
    
                } */
    
    
            }
            
            
        }
    
    
    
    
        // Sort the list in order of birthday, IGNORING THE YEAR!!!
    
    
        // print output
    
    
    
    
        fclose(ifp);
        
        return 0;
    }
    But now I am getting an error that says:
    Code:
    birthday.c: In function ‘main’:
    birthday.c:48: error: invalid type argument of ‘unary *’
    birthday.c:49: error: invalid type argument of ‘unary *’


    Also, I am not the best when thinking about what variables need to be dynamically allocated or not, in my structs should I have everything as a pointer? Or is first name and last name only as pointers correct?

  7. #7
    Registered User
    Join Date
    Nov 2011
    Location
    Saratoga, California, USA
    Posts
    334
    Quote Originally Posted by C0__0D View Post
    Also, I am not the best when thinking about what variables need to be dynamically allocated or not, in my structs should I have everything as a pointer? Or is first name and last name only as pointers correct?
    Then do what we all do - get out a pencil and paper and diagram your data objects so can see what you have and/or what you want to have.

    You don't "need" pointers, you could just as viably have fixed-sized arrays, but dynamic allocation allows you to not waste space. Having to accommodate a name like "Srinivasaraghavan" when most names are more like "Smith", it might make sense to use dynamic allocation. (Of course, always follow your assignment spec).

  8. #8
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Code:
    // Allocating space for the students in the classroom
    person *student = malloc(sizeof(person)*num_students);
    student->first_name = malloc(sizeof((char) * MAX_CHARS_IN_NAME)*num_students);
    student->last_name = malloc(sizeof((char) * MAX_CHARS_IN_NAME)*num_students);
    At the first line above you allocate memory for num_students person structures, i.e. you can use the memory as an array of num_students person structures.
    Inside each structure you have two char pointers for which you have to allocate memory too. All in all you need 2 * num_students malloc() calls to allocate memory for all char pointers. Does this sound like using a for-loop will be convenient?

    If you don't understand the above I think you should stick to fixed-sized char arrays for the moment and spend some time reading through a tutorial like Ted Jensen's "Tutorial on Pointers and Arrays".

    Bye, Andreas

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    This is not how you allocate each student's name:
    Code:
        student->first_name = malloc(sizeof((char) * MAX_CHARS_IN_NAME)*num_students);
        student->last_name = malloc(sizeof((char) * MAX_CHARS_IN_NAME)*num_students);
    Each student[j] has its own name pointer. Like Tclausx says, diagram your data.

    To understand your compiler error, parse malloc's argument:
    sizeof(
    (char) - a cast to char type, supposed to be one of the multiplication operator's argument.
    * - supposed to be the multiplication operator
    MAX_CHARS_IN_NAME) - supposed to be one of the multiplication operator's argument.

    The compiler errors out because you cannot multiply something like this. A cast is an operation that also needs an operand, so (char)operand * MAX_CHARS_IN_NAME makes sense but what you wrote does not.

    sizeof(char) is always 1 because of the C standard's requirements. Thus, multiplying when you are allocating many characters is unnecessary.

  10. #10
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    sizeof(char) is always 1 because of the C standard's requirements
    I'm on my iPad and can't "control f" to search the standards draft - What section is that in?
    Fact - Beethoven wrote his first symphony in C

  11. #11
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    In C99 5.2.4.2.1 Sizes of integer types <limits.h>

  12. #12
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by Click_here View Post
    I'm on my iPad and can't "control f" to search the standards draft - What section is that in?
    6.5.3.4 The sizeof operator in PDF n1362.pdf (ISO/IEC 9899:201x)
    in numbered sub-section/paragraph 3. In PDF n1570.pdf its is in numbered sub-section/paragraph 2.

    3 When applied to an operand that has type char, unsigned char,or signed char,
    (or a qualified version thereof) the result is 1.
    Tim S.
    Last edited by stahta01; 03-04-2013 at 04:24 PM.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  13. #13
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    I've always thought that the size of char in bytes is not guaranteed to be 1 byte.

    I learn something new every day
    Fact - Beethoven wrote his first symphony in C

  14. #14
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by Click_here View Post
    I've always thought that the size of char in bytes is not guaranteed to be 1 byte.

    I learn something new every day
    A year ago, I thought that but this sites mentions the topic about once every two months.

    NOTE: I still believe it can be something other that 1 on NON C standard compilers.
    Just to be a C standard compiler is must be 1.

    Can anyone confirm this idea?

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  15. #15
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    On a non-standard compiler, a char can be an old wooden ship.

    If you start getting old wooden ships instead of one byte, change your compiler to a standard one.
    Fact - Beethoven wrote his first symphony in C

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Segmentation fault
    By BigAll in forum C++ Programming
    Replies: 1
    Last Post: 12-10-2006, 06:25 AM
  2. Segmentation Fault
    By blaksheep423 in forum C Programming
    Replies: 11
    Last Post: 12-07-2006, 05:28 AM
  3. segmentation fault?
    By kalleanka in forum C Programming
    Replies: 4
    Last Post: 11-20-2006, 03:03 PM
  4. Segmentation Fault
    By ammalik in forum C++ Programming
    Replies: 1
    Last Post: 11-06-2006, 05:06 PM
  5. segmentation fault and memory fault
    By Unregistered in forum C Programming
    Replies: 12
    Last Post: 04-02-2002, 11:09 PM