0
votes

Why am I getting a segmentationfault when it tries to print the second member in the list?

After printing the first element of the list, the debugger opens the stdio.h and says:

At C:\TDM-GCC-32\include\stdio.h:255
At C:\TDM-GCC-32\include\stdio.h:256
At C:\TDM-GCC-32\include\stdio.h:258
At C:\TDM-GCC-32\include\stdio.h:259

Here is the code.

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

struct Student {
    char *Name;
    char *Adresse;
    unsigned long Mtnr;
    short Kurse;

    struct Student *next;
    struct Student *previous;
};

typedef struct Student Student;

Student *liste = NULL, *ende = NULL;

void add(char Name, char Adresse, unsigned long Mtnr, short Kurse) {
    Student *add;

    ende->next = malloc(sizeof(Student));
    add = ende->next;

    add->Name = Name;
    add->Adresse = Adresse;
    add->Mtnr = Mtnr;
    add->Kurse = Kurse;
    add->previous = ende;
    add->next = NULL;
    ende = ende->next;
}

void Ausgabe(Student *Anfang) {

    while (Anfang != NULL) {
        printf("%s %s %d %d \n", Anfang->Name, Anfang->Adresse, Anfang->Mtnr, Anfang->Kurse);
        Anfang = Anfang->next;
    }
}

int main() {
    liste = malloc(sizeof(Student));
    ende = liste;
    liste->Name = "Anna Musterfrau";
    liste->Adresse = "Am Schwarzberg-Campus 3";
    liste->Mtnr = 22222;
    liste->Kurse = 2;
    liste->next = NULL;
    liste->previous = NULL;

    add("Hans Peter", "Kasernenstrasse 4", 4444, 4);

    Ausgabe(liste);

    return 0;
}
3
%d is not for unsigned long..... %lu seems suitableSourav Ghosh

3 Answers

4
votes

The error is in the declaration of the add() function. The strings should be char pointers, not chars.

void add(char *Name, char *Adresse, unsigned long Mtnr, short Kurse){
1
votes

The signature of the function add is inconsistent to the declaration and usage to the members of Student. Change the signature as follows.

void add(char* Name, char* Adresse, unsigned long Mtnr, short Kurse)

On the long run, it might also be necessary to create copies of Name and Adresse in add, as the caller of add might deallocate them, perhaps causing undesired behaviour.

0
votes

While Marc Is correct with his observation, there is one more thing you may want to fix here.

When you add a record, you allocate it, but you do not allocate the content of it's pointers (Specifically = for the name and address pointers). The add function just point them to the input's address. this is a problem because the data in the address supplied to the add function is likely to change if, for example, it's a user input, or some other external buffer.

in the code snipped below I fixed the 'name', but left the address as is. please run it and see what happens. (assaf's record displays david's address)

hope this helps

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

struct Student {
    char *Name;
    char *Adresse;
    unsigned long Mtnr;
    short Kurse;

    struct Student *next;
    struct Student *previous;
};

typedef struct Student Student;

Student *liste = NULL, *ende = NULL;

void add(char *Name, char *Adresse, unsigned long Mtnr, short Kurse) {
    Student *add;

    ende->next = malloc(sizeof(Student));
    add = ende->next;

    add->Name = malloc(strlen(Name)+1);
    strcpy(add->Name, Name);
    add->Adresse = Adresse;
    add->Mtnr = Mtnr;
    add->Kurse = Kurse;
    add->previous = ende;
    add->next = NULL;
    ende = ende->next;
}

void Ausgabe(Student *Anfang) {

    while (Anfang != NULL) {
        printf("%s %s %d %d \n", Anfang->Name, Anfang->Adresse, Anfang->Mtnr, Anfang->Kurse);
        Anfang = Anfang->next;
    }
}

int main() {
    char name_buf[100];
    char address_buf[100];
    liste = malloc(sizeof(Student));
    ende = liste;
    liste->Name = "Anna Musterfrau";
    liste->Adresse = "Am Schwarzberg-Campus 3";
    liste->Mtnr = 22222;
    liste->Kurse = 2;
    liste->next = NULL;
    liste->previous = NULL;

    add("Hans Peter", "Kasernenstrasse 4", 4444, 4);

    sprintf(name_buf,"assaf stoler");
    sprintf(address_buf,"maria 8");
    add(name_buf, address_buf, 8888, 8);

    sprintf(name_buf,"david david");
    sprintf(address_buf,"some street 9");
    add(name_buf, address_buf, 9999, 9);


    Ausgabe(liste);

    return 0;
}

EDIT: Op asked some questions, and the comment space is limited, so I'll add below:

A pointer is just an object pointing somewhere in memory. it's size is fixed. the content it's pointing to will vary.

When you include a pointer to a string in a structure, the space where the string is kept need to be allocated / accounted for. it is not part of the sizeof(struct).

In your original example the pointers were pointing to constant strings (which reside in the static code, usually the data section, allocated by the compiler), which is why your original code was able to access the strings.

In a more realistic case, the input data is not part of the program data, but is received by some input method (which my *buf was to emulate). as such, pointing your name and address at it would break the program, as the pointer you point to may have it's content changed. therefor copying of the data (string / array) is needed, and since we copy the data, we need to allocate space for it, and point our (name/address) pointer at it.

Alternate option is to use non-pointer array for name and address as in:

struct Student {
    char Name[20];
    char Adresse[60];
    unsigned long Mtnr;
    ...
}

In this scenario, sizeof (struct Student) would actually include all the space for those fields. you still need to use strcpy or memcpy, as well as check for and handle strings that are too long to fit in your pre-defined length.

Hope this helps