Hello,
I was just trying to write some simple codes to learn C. I wrote 3 functions, create a list,print a list and free a list.

but i get segfault while printing the list. (by the way, list is not a list datastructure. it's just an array)
In create_list, I get memory blocks dynamicaly so why does it complain in print_list function?


here the code:

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

#define N 1

struct A
{
        int x;
        char* str;
};

int create_list(struct A* list);
void print_list(struct A* list);
void free_list(struct A* list);

int main(int argc, char** argv)
{
                struct A* list;
                create_list(list);
                print_list(list);
                free_list(list);
}
int create_list(struct A* list)
{
        int i = 0;
        list = (struct A*) malloc(N*sizeof(struct A));
        char buf[100];
        for (i=0;i<N;i++)
        {
                list[i].x=i;
                sprintf(buf, "%s%d", "element", i);
                list[i].str = strdup(buf);
        }
}
void print_list(struct A* list)
{
        int i = 0;
        for (i=0; i<N; i++)
        {
                         printf("element %d, x:%d str:%s\n", i, list[i].x, list[i].str);
        }
}
void free_list(struct A* list)
{
        int i = 0;
        for (i=0; i<N; i++)
        {
                free(list[i].str);
        }
        free(list);
        list=NULL;
}

C does not have pass by reference, but you can fake it by passing pointers and using indirection to get to the original object:

#include <stdio.h>

void nochangex(int x)
{
    x = 123;
}

void changex(int* x)
{
    *x = 123;
}

int main()
{
    int x = 0;

    printf("before nochangex %d\n", x);
    nochangex(x);
    printf("after nochangex %d\n", x);

    printf("before changex %d\n", x);
    changex(&x);
    printf("after changex %d\n", x);

    return 0;
}

Pointers are also passed by value, so just like x, if you want to change a pointer, you need to pass a pointer to that pointer:

#include <stdio.h>

static int global = 123;

void nochangep(int *p)
{
    p = &global;
}

void changep(int** p)
{
    *p = &global;
}

int main()
{
    int local = 0;
    int* p = &local;

    printf("before nochangep %d\n", *p);
    nochangep(p);
    printf("after nochangep %d\n", *p);

    printf("before changep %d\n", *p);
    changep(&p);
    printf("after changep %d\n", *p);

    return 0;
}

The reason your print_list() function fails is because in main(), the list pointer is still uninitialized even after calling create_list(). Any changes made in create_list() are made on a copy of the pointer from main(), so the pointer in main() is unchanged. You can prove this by making a quick change to main():

int main(int argc, char** argv)
{
    struct A* list = NULL;
    create_list(list);
    if (!list) printf("list is null!\n");
    else
    {
        print_list(list);
        free_list(list);
    }
    return 0;
}
This article has been dead for over six months. Start a new discussion instead.