【问题标题】:Why the program crased even thoungh I got the correct result?为什么即使我得到正确的结果程序也会崩溃?
【发布时间】:2019-09-27 23:37:42
【问题描述】:

我正在学习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 然后程序崩溃了

【问题讨论】:

    标签: c pointers pass-by-value


    【解决方案1】:

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

    所以,在你的代码中

    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 使用按值传递,所以如果你必须修改参数本身,你需要传递一个指向它的指针。类似的东西

    InitList(&L);
    

    然后,

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

    应该做的工作。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        实际上,我很惊讶它恰好在您的机器上运行。 (它在技术上称为undefined behaviour,可以以多种方式表现出来,包括没有明显的症状。)

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

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

        然后你需要这样称呼它:

        InitList(&L);
        

        【讨论】:

          猜你喜欢
          • 2016-01-24
          • 1970-01-01
          • 2012-08-31
          • 2017-03-26
          • 2020-08-04
          • 1970-01-01
          • 1970-01-01
          • 2021-01-14
          • 2012-06-04
          相关资源
          最近更新 更多