为什么即使我得到了正确的结果,该程序也崩溃了?

时间:2019-05-10 05:28:01

标签: c pointers pass-by-value

我正在学习LinkList的数据结构,并且已经实现了适用于我的源代码。今天,我尝试用下面的另一种方式来做。而且我感到困惑,为什么即使我得到了想要的结果,程序也会崩溃。

#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;
}

结果是:成功! 1 6 4 6 1 1 8 2 8 2 然后程序崩溃了

3 个答案:

答案 0 :(得分:2)

这里的问题是,您在L内分配给InitList()的任何内存都不会反映回调用时传递给函数的实际参数。

所以,在您的代码中

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;
}

在点(2),L尚未初始化。访问将调用undefined behaviour

C使用传递值,因此,如果必须修改参数 itself ,则需要传递一个指向该参数的指针。像

InitList(&L);

然后

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

    return OK;
}

应该做这项工作。

答案 1 :(得分:1)

问题是InitList初始化L的本地副本,但不初始化L函数中的main的本地副本。将其更改为InitList(LinkList **L)并以InitList(&L);调用,并相应地更改您的实现。

答案 2 :(得分:0)

我真的很惊讶它首先在您的计算机上运行。 (这在技术上称为undefined behaviour,可以通过多种方式表现出来,包括没有明显的症状。)

无论如何,InitList中有一个直接的问题:在此处设置L时,新分配的指针不会传播回调用者。为此,您需要将其转换为指向指针的指针:

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

    return OK;
}

然后您需要像这样调用它:

InitList(&L);