Robert777
Robert777

Reputation: 801

Why am I getting Segmentation fault?

I am trying to learn how to use structures and linked lists in C but I really don't understand why the following code gives me Segmentation fault:

I have 3 files named list.h, operations.c and main.c. In the file list.h:

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

typedef char DATA;

struct linked_list {
    DATA                   d;
    struct linked_list *next;
};

typedef struct linked_list ELEMENT;
typedef ELEMENT              *LINK;

LINK string_to_list(char s[]);
void print_list(LINK);

The file operations.c:

#include "list.h"

LINK string_to_list(char s[]){
    LINK head = NULL;

    if (s[0]) {
        ELEMENT c = {s[0], NULL};
        c.next = string_to_list(s+1);
        head = &c;
    }

    return head;
}

void print_list(LINK head) {
    if(head != NULL){
        putchar(head -> d);
        print_list(head -> next);
    } else {
        putchar('\n');
    }
}

The file main.c:

#include "list.h"

int main(void) {
    LINK head = string_to_list("wtf");
    print_list(head);
    return 0;
}

Upvotes: 1

Views: 108

Answers (3)

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158469

In string_to_list you are taking the address of a local variable(which on most modern implementations is stored on the stack) in your if statement:

head = &c;

and then returning that address here:

return head;

the variable c will no longer exist after the end of the if statement, this is undefined behavior. The C99 draft standard section 6.2.4 Storage durations of objects paragraph 2 says:

[...]If an object is referred to outside of its lifetime, the behavior is undefined.[...]

Upvotes: 2

Michael Dorgan
Michael Dorgan

Reputation: 12515

if (s[0]) {
--->    ELEMENT c = {s[0], NULL};
    c.next = string_to_list(s+1);
    head = &c;
}

return head;

Is a local memory. As soon as you leave the function (or even the code block), that memory is freed and is no longer valid. You need to malloc() it, or pass in some memory for this function to use for it to live beyond this function.

Upvotes: 2

Joachim Isaksson
Joachim Isaksson

Reputation: 180917

if (s[0]) {
    ELEMENT c = {s[0], NULL};        // Allocate space for struct on the stack
    c.next = string_to_list(s+1);
    head = &c;                       // Save the address to head
}  // <-- poof, c goes out of scope and is deallocated from the stack

return head; // <-- return address of deallocated object

Upvotes: 4

Related Questions