数据结构实践——初始化顺序表怎么就内存溢出了?

最后更新于:2022-04-01 14:38:25

  有学生调程序,是要建顺序表。   他的程序是这样的: ~~~ #include <stdio.h> #include <malloc.h> #define MaxSize 50 //Maxsize将用于后面定义存储空间的大小 typedef int ElemType; //ElemType在不同场合可以根据问题的需要确定,在此取简单的int typedef struct { ElemType data[MaxSize]; //利用了前面MaxSize和ElemType的定义 int length; } SqList; //声明自定义函数 SqList InitList(SqList *L); //初始化顺序表 void ListInsert(SqList *L,int i,int b); //插入函数 void DispList(SqList *L); //输出函数 bool ListEmpty(SqList *L);//判定是否为空表ListEmpty(L) int main() { SqList *sq; InitList(sq); ListInsert(sq, 1, 5); ListInsert(sq, 2, 3); ListInsert(sq, 1, 4); DispList(sq); return 0; } //输出线性表DispList(L) void DispList(SqList *L) { int i; if (ListEmpty(L)) return; for (i=0; i<L->length; i++) printf("%d ",L->data[i]); printf("\n"); } //判定是否为空表ListEmpty(L) bool ListEmpty(SqList *L) { return(L->length==0); } //初始化顺序表InitList(*L) SqList InitList(SqList *L) { L=(SqList *)malloc(sizeof(SqList));//这里申请了结点空间 L->length=0; return *L; } void ListInsert(SqList *L,int i,int b) //插入函数 { int j,k; if(i<1) { printf("插入位置非法/n"); } for(j=L->length; j>i; j--) { L->data[j]=L->data[j-1]; } L->data[i]=b; L->length++; } ~~~   运行结果是这样的: ![这里写图片描述](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-07_57564049a297f.jpg "")   他找我帮忙。基本可以断定,内存使用不当,有溢出。   看一下编译提示的信息,有一个警告:   D:\CB\DS\main.cpp|21|warning: ‘sq’ is used uninitialized in this function [-Wuninitialized]|   说在21行,sq未经初始化就使用了。通俗的说法,野指针。   围绕着sq找。在main()函数中有: ~~~ SqList *sq; InitList(sq); ~~~   这里在调用InitList时,实际参数sq就是野指针。但这还不是出问题的关键,看InitList函数的定义是: ~~~ //初始化顺序表InitList(*L) SqList InitList(SqList *L) { L=(SqList *)malloc(sizeof(SqList));//这里申请了结点空间 L->length=0; return *L; } ~~~   调用时,L得到的是野指针,但在函数里为其分配空间了。但调用完,这个地址并未返回到main函数中。调用完InitList,sq仍然还是野指针。这是关键!   沿这个思路,希望能将分配的空间地址能返回给main函数。return *L就不合适了,return L是返回地址。于是,函数定义改为: ~~~ //初始化顺序表InitList(*L) SqList *InitList(SqList *L) { L=(SqList *)malloc(sizeof(SqList));//这里申请了结点空间 L->length=0; return L; } ~~~   既然参数SqList *L调用时给的是个野指针,不要也罢。于是改选成无参函数: ~~~ //初始化顺序表InitList(*L) SqList *InitList() { SqList *L=(SqList *)malloc(sizeof(SqList));//这里申请了结点空间 L->length=0; return L; } ~~~   在调用时,main函数定义为: ~~~ int main() { SqList *sq; sq = InitList(); ListInsert(sq, 1, 5); ListInsert(sq, 2, 3); ListInsert(sq, 1, 4); DispList(sq); return 0; } ~~~   为保证程序能够正确编译,函数声明等处的语法问题不一一列出。解决了这一环节的问题,程序能够运行了,但结果:   ![这里写图片描述](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-07_57564049b75fd.jpg "")   断定问题出在ListInsert函数中。看调用,插入的位置用的是逻辑序(从1开始记数),但函数定义中,直接L->data[i]=b;没有考虑物理存储中,下标是从0开始的。   所以,在ListInsert中加入一个 i–,完成逻辑序号向物理序号的转换,Done。   正确的结果不贴图了,最后改过的程序是: ~~~ #include <stdio.h> #include <malloc.h> #define MaxSize 50 //Maxsize将用于后面定义存储空间的大小 typedef int ElemType; //ElemType在不同场合可以根据问题的需要确定,在此取简单的int typedef struct { ElemType data[MaxSize]; //利用了前面MaxSize和ElemType的定义 int length; } SqList; //声明自定义函数 SqList *InitList(); //初始化顺序表 void ListInsert(SqList *L,int i,int b); //插入函数 void DispList(SqList *L); //输出函数 bool ListEmpty(SqList *L);//判定是否为空表ListEmpty(L) int main() { SqList *sq; sq = InitList(); ListInsert(sq, 1, 5); ListInsert(sq, 2, 3); ListInsert(sq, 1, 4); DispList(sq); return 0; } //输出线性表DispList(L) void DispList(SqList *L) { int i; if (ListEmpty(L)) return; for (i=0; i<L->length; i++) printf("%d ",L->data[i]); printf("\n"); } //判定是否为空表ListEmpty(L) bool ListEmpty(SqList *L) { return(L->length==0); } //初始化顺序表InitList(*L) SqList *InitList() { SqList *L=(SqList *)malloc(sizeof(SqList));//这里申请了结点空间 L->length=0; return L; } void ListInsert(SqList *L,int i,int b) //插入函数 { int j; if(i<1) { printf("插入位置非法/n"); } i--; for(j=L->length; j>i; j--) { L->data[j]=L->data[j-1]; } L->data[i]=b; L->length++; } ~~~
';