为什么即使我得到了正确的结果程序也会崩溃?
Why the program crased even thoungh I got the correct result?
我正在学习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
然后程序崩溃了
这里的问题是,无论您在 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 使用 pass-by-value,所以如果你必须修改参数 本身 ,你需要传递一个指向它的指针。像
InitList(&L);
然后,
Status InitList(LinkList **L)
{
*L = malloc(sizeof(**L));
if(!*L) return ERROR;
(*L)->next = NULL;
return OK;
}
应该完成这项工作。
我真的很惊讶它一开始就可以在你的机器上运行。 (这在技术上被称为 undefined behaviour,可以通过多种方式表现出来,包括没有明显的症状。)
无论如何,一个紧迫的问题是 InitList
:当您在那里设置 L
时,新分配的指针不会传播回调用者。为此,您需要将其变成指向指针的指针:
Status InitList(LinkList **L)
{
*L = malloc(sizeof(LinkList));
if(!*L) return ERROR;
(*L)->next = NULL;
return OK;
}
然后您需要这样调用它:
InitList(&L);
问题是 InitList
初始化了 L
的本地副本,而不是 main
函数中的 L
。将其更改为 InitList(LinkList **L)
并调用为 InitList(&L);
,并相应地更改您的实现。
我正在学习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 然后程序崩溃了
这里的问题是,无论您在 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 使用 pass-by-value,所以如果你必须修改参数 本身 ,你需要传递一个指向它的指针。像
InitList(&L);
然后,
Status InitList(LinkList **L)
{
*L = malloc(sizeof(**L));
if(!*L) return ERROR;
(*L)->next = NULL;
return OK;
}
应该完成这项工作。
我真的很惊讶它一开始就可以在你的机器上运行。 (这在技术上被称为 undefined behaviour,可以通过多种方式表现出来,包括没有明显的症状。)
无论如何,一个紧迫的问题是 InitList
:当您在那里设置 L
时,新分配的指针不会传播回调用者。为此,您需要将其变成指向指针的指针:
Status InitList(LinkList **L)
{
*L = malloc(sizeof(LinkList));
if(!*L) return ERROR;
(*L)->next = NULL;
return OK;
}
然后您需要这样调用它:
InitList(&L);
问题是 InitList
初始化了 L
的本地副本,而不是 main
函数中的 L
。将其更改为 InitList(LinkList **L)
并调用为 InitList(&L);
,并相应地更改您的实现。