I am learning the data structure of LinkList, and I have already implemented the source code that works for me. Today I try to do it in another way like below. And I am confusing why the programe will be crashed even though I get the result I want.

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

#define OK 1
#define ERROR 0

typedef int ElemType;
typedef int Status;

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode, LinkList;   //I don't use the *LinkList on purpose to check it out

//Initialize LinkList: Create a head node
Status InitList(LinkList *L)
{
    L = malloc(sizeof(LinkList));
    if(!L) return ERROR;
    L->next = NULL;

    return OK;
}

//CreateList
Status CreateListHead(LinkList *L, int n)
{
    LinkList *s;
    int i;

    if(n < 1) return ERROR;
    InitList(L);
    srand(time(0));

    for(i=0; i<n; i++)
    {
        s = malloc(sizeof(LinkList));
        if(!s)  return ERROR;
        s->data = rand()%10+1;
        s->next = L->next;
        L->next = s;
    }

    return OK;
}

//Travese LinkList
void Traverse(LinkList *L)
{
    while(L->next)
    {
        printf("%d ", L->next->data);
        L->next = L->next->next;
    }
}

int main()
{
    LinkList *L;
    int s;

    s = InitList(L);
    if(s) printf("Successful´╝ü");
    else printf("Failed!");

    CreateListHead(L, 10);

    Traverse(L);
    return 0;
}

And the result is: Succesful! 1 6 4 6 1 1 8 2 8 2 And then the program crashed

3 Answers

2
Sourav Ghosh On Best Solutions

The problem here is, whatever memory you allocate to L inside InitList(), is not going to be reflected back to the actual argument passed to the function when being called.

So, in your code

if(n < 1) return ERROR;
InitList(L);               ----------------(1)
srand(time(0));

for(i=0; i<n; i++)
{
    s = malloc(sizeof(LinkList));
    if(!s)  return ERROR;
    s->data = rand()%10+1;
    s->next = L->next; -------------------(2)
    L->next = s;
}

at point (2), L is still uninitialized. Accessing that will invoke undefined behaviour.

C uses pass-by-value, so if you have to modify the argument itself, you need to pass a pointer to that. Something like

InitList(&L);

and then,

Status InitList(LinkList **L)
{
    *L = malloc(sizeof(**L));
    if(!*L) return ERROR;
    (*L)->next = NULL;

    return OK;
}

should do the job.

0
NPE On

I am actually pretty surprised that it happens to work on your machine in the first place. (It's what's technically known as undefined behaviour and can manifest itself in a variety of ways, including no visible symptomps.)

Anyway, one immediate issue is in InitList: when you set L there, the newly allocated pointer does not propagate back the caller. For that you need to turn it into a pointer to pointer:

Status InitList(LinkList **L)
{
    *L = malloc(sizeof(LinkList));
    if(!*L) return ERROR;
    (*L)->next = NULL;

    return OK;
}

You'll then need to call it like so:

InitList(&L);
1
Ali On

Problem is InitList initializes a local copy of L, but not the L that is in your main function. Change it to InitList(LinkList **L) and call as InitList(&L);, and change your implementation accordingly.