mneumann mneumann - 2 months ago 8
C Question

Segmentation Fault when calling member of a struct

sorry if this has been asked a million times before, but I think I have a problem understanding how strings (char arrays) work in C.

In my program, I have a "stack" struct, which looks like this (in stack.h):

struct stack_t {
/* Stack-Datentyp */
/* Stacks have a head-node, a length, and a name.
Stacks are filled with links (nodes) that are defined below. These links have
a generic data pointer and a pointer to the next link */
link head;
unsigned int length;
char *name; //stack name
};

typedef struct stack_t *stack;


in my main.c, I call a function called "stack_new" which seems to work properly, since all the printf-calls work:

stack stack_new(char *stackname) {
/* creates a new, empty stack */
stack st = (stack)(malloc(sizeof(stack)));
if (st == NULL) {
fprintf(stderr, "Error: Memory for Stack could not be allocated!\n");
return NULL;
}
st->head = NULL;
printf("head works.\n");
st->length = 0;
printf("length works.\n");
st->name = stackname;
printf("stackname works.\n");
return st;
}


Now, when I call this function in main.c, I get a seg fault. Here is the call:

if (strcmp(input,"newstack") == 0) {
printf("Please enter stackname:\n");
scanf("%s", &stackname);
printf("Debug: Input works.\n");
stacklist[NumberOfStacks] = stack_new(stackname);
printf("stack created works-\n");
NumberOfStacks++;
printf("A new stack with the name '%s' was created!\nIt is number %d in stack list.", stacklist[NumberOfStacks]->name, NumberOfStacks);
continue;
}


The seg fault happens when I try to print the member name of the struct stacklist[NumberOfStacks] points to. What am I doing wrong here?

I also get a bunch of warnings that tell me about how my scanf for stackname expects a different type:


warning: format ‘%s’ expects argument of type ‘char ’, but argument 2 has type ‘char ()[50]’ [-Wformat=]
scanf("%s", &stackname);


Other warnings I get tell me that I am not typecasting from my void-pointer I use for data storage in the stack nodes, but I don't think that this is relevant to my problem here.

Thank you for your help!

Edit:
The problem was that I incremented NumberOfStacks before using it as index for printing the member of a struct saved in the array.

NumberOfStacks++;
printf("A new stack with the name '%s' was created!\nIt is number %d in stack list.", stacklist[NumberOfStacks]->name, NumberOfStacks);


This part of the program works fine now, thanks!

Answer

There are a couple of bugs in your code. Most have been addressed in the comments. I have made the corrections and it seems to work without segfault. The modifications are indicated by comments in the code.

This is the code I ended up with:

#include <stdio.h>
// Prototype for malloc
#include <stdlib.h>
// Prototype for strdup
#include <string.h>

typedef void *link; /* Added to make it compile - you may have a different definition in your code */

struct stack_t {
    /* Stack-Datentyp */
    /* Stacks have a head-node, a length, and a name.
     * Stacks are filled with links (nodes) that are defined below. 
     * These links have
     * a generic data pointer and a pointer to the next link */
    link head;
    unsigned int length;
    char *name;                     //stack name
};

typedef struct stack_t *stack;

stack stack_new(char *stackname) {
    /* creates a new, empty stack */
    stack st = malloc(sizeof(*st));    // changed to use the variable name
    if (st == NULL) {
        fprintf(stderr, "Error: Memory for Stack could not be allocated!\n");
        return NULL;
    }
    st->head = NULL;
    printf("head works.\n");
    st->length = 0;
    printf("length works.\n");
    st->name = strdup(stackname);  // Changed: Duplicate the name so it won't get overwritten when creating the next stack
    printf("stackname works.\n");
    return st;
}


int main(void)
{
    char stackname[50];       // Added declaration for stackname.
    stack stacklist[50];      // Added declaration. Can handle up to 50 stacks.
    int NumberOfStacks = 0;

    printf("Please enter stackname:\n");
    scanf("%s", stackname);              // Changed. Removed the "&" since stackname is a char*.
    printf("Debug: Input works.\n");
    stacklist[NumberOfStacks] = stack_new(stackname);
    printf("stack created works-\n");
    // All data is at index 0, so cannot use increased value of NumberOfStacks to get get the data. Also changed the text to "has index" since a 0 will be printed for stacknumber.
    printf("A new stack with the name '%s' was created!\nIt has index %d in stack list.\n", stacklist[NumberOfStacks]->name, NumberOfStacks);
    NumberOfStacks++;    // Moved this line down.
    return 0;
}