C++里加了delete语句就报错,不加就可以运行,请问我释放内存的操作哪里有问题?
本帖最后由 菜鸟小乔 于 2019-6-1 16:14 编辑代码功能:创建循环链表,实现初始化赋值、插入元素的功能。(目前只写了插入函数、初始化函数)
问题描述:在插入函数和打印函数里,用new分配内存,在函数结尾delete释放——报错读取访问冲突。
如果把delete语句注释掉程序就可以运行,但感觉这样不严谨。
求助大神们帮忙看看,我的delete语句为什么释放内存出错?
完整代码如下:(出错的delete语句在.cpp文件69行处、94行处)
--------C_list.h文件---------数据类型定义、函数声明---------------------------
#ifndef CircularLinkList_h_include
#define CircularLinkList_h_include
/* 《循环链表》
*/
#include<iostream>
#include<string>
using namespace std;
//#define MAX_SIZE 255
//#defineTRUE 1
//#defineFALSE 0
//定义一种数据类型
typedef struct {
int id;
string name ="初始名字";
}EleType;
//循环链表节点,
typedef struct Node {
EleType data;
struct Node* next;
}Node;
//定义 循环链表的结构
typedef struct C_LinkList {
Node* next; //头指针(有头节点,)
int length; //链表长度,初始值为0.
}C_LinkList;
//插入元素
void Insert(C_LinkList* list_c, int pos, EleType element);
//初始化
void Init(C_LinkList* list_c, EleType* dataArray, int len);
//打印
void Print(C_LinkList* list_c);
#endif
--------.cpp文件------------函数实现-------------------------
#include<iostream>
#include<string>
#include"C_list.h"
using namespace std;
//初始化
void Init(C_LinkList* list_c, EleType* dataArray, int len)
{
for (int i = 0; i < len; i++)
{
Insert(list_c, i + 1, dataArray);
}
}
//插入元素
void Insert(C_LinkList* list_c, int pos, EleType element)
{
Node* node = new Node;
node->data = element;
// element.id = 5;
// element.name = "名字";
node->next = NULL;
if (pos == 1)
{
node->next = list_c->next;
if (!node->next) //如果链表长度为零
{
//cout << "长度为零" << endl;
node->next = node;
}
else//长度不为零,找到最后一个节点,并改变其指针域
{
//cout << "长度不为零" << endl;
Node* lastnode = list_c->next;
for (int i = 1; i < list_c->length; i++)
{
lastnode = lastnode->next;
}
lastnode->next = node;
}
list_c->next = node;
list_c->length++;
return;
}//
//cout << "pos不等于1" << endl; //插入pos不是第一个,从第一个开始遍历
Node* currNode = new Node;
currNode->next = NULL;
currNode = list_c->next;
for (int i = 1; currNode && i < pos - 1; i++)
{
currNode = currNode->next;
}
if (currNode)
{
//cout << "pos不等于1" << endl;
node->next = currNode->next;
currNode->next = node;
list_c->length++;
if (pos == list_c->length)//如果是最后一个结点
{
node->next = list_c->next;//改变最后一个节点的指针域为指向第一个结点
}
}
//delete node; //这里4行释放内存的语句加进去,也报错读取访问冲突。
//node = NULL;
//delete currNode;
//currNode->next = NULL;
}
///////////////////////////////////
void Print(C_LinkList *list_c)
{
if (list_c->length == 0 || list_c->next == NULL)
{
cout << "链表为空,无内容可打印!" << endl;
list_c->length = 0;
return;
}
Node* node = new Node;
node->next = NULL;
node = list_c->next; //创建临时结点第一个结点开始遍历
for (int i = 0; i < list_c->length; i++)
{
cout << node->data.id << ":" << node->data.name << endl;
node = node->next;
}
//delete node; //添加delete就会报错,访问冲突。
//node = NULL;
cout << "*****打印结束*******" << endl;
}
--------main.cpp文件----------------------------
#include<iostream>
#include<string>
#include"C_list.h"
using namespace std;
//测试数据
EleType dataArray[]{
{1,"香蕉"},
{2,"樱桃"},
{3,"菠萝"},
{4,"苹果"}
};
//测试函数
void test();
int main()
{
test();
return 0;
}
////////////////
void test()
{
C_LinkList* clist = new C_LinkList;
clist->next = NULL;
clist->length = 0;
Init(clist, dataArray, 4);//初始化赋值
Print(clist);//打印
Insert(clist, 1, dataArray);//插入
Print(clist);//打印
Insert(clist, 2, dataArray);
Print(clist);//打印
delete clist;
clist = NULL;
}
本帖最后由 Krant5 于 2019-6-1 16:52 编辑
new出来的节点,刚刚才插入链表,是不能释放的 在销毁链表时候释放就好 Krant5 发表于 2019-6-1 16:33
好好的new出来的节点,刚刚才插入链表,你释放他干啥啊? 就不能销毁链表时候再释放吗?,你这是在破坏链表结构
我把它理解为:相当于一个临时变量,函数执行完了,就没用了。。。。
而且函数内部的new出来的变量,只能用在函数内部,释放也应该在函数内部释放吧。。。。
是我理解错了吗?
菜鸟小乔 发表于 2019-6-1 16:53
我把它理解为:相当于一个临时变量,函数执行完了,就没用了。。。。
而且函数内部的new出来的变量, ...
那你就用局部变量咯,插入链表的还是new出来那个对象,是不能释放的 Krant5 发表于 2019-6-1 16:58
那你就用局部变量咯,插入链表的还是new出来那个对象,是不能释放的
下面这段插入功能的函数,node是在这个函数里定义的,难道它不是局部变量吗?{:9_241:}
void Insert(C_LinkList* list_c, int pos, EleType element)
{
Node* node = new Node;
node->data = element;
// element.id = 5;
// element.name = "名字";
node->next = NULL;
if (pos == 1)
{
node->next = list_c->next;
if (!node->next) //如果链表长度为零
{
//cout << "长度为零" << endl;
node->next = node;
}
else//长度不为零,找到最后一个节点,并改变其指针域
{
//cout << "长度不为零" << endl;
Node* lastnode = list_c->next;
for (int i = 1; i < list_c->length; i++)
{
lastnode = lastnode->next;
}
lastnode->next = node;
}
list_c->next = node;
list_c->length++;
return;
}//
//cout << "pos不等于1" << endl; //插入pos不是第一个,从第一个开始遍历
Node* currNode = new Node;
currNode->next = NULL;
currNode = list_c->next;
for (int i = 1; currNode && i < pos - 1; i++)
{
currNode = currNode->next;
}
if (currNode)
{
//cout << "pos不等于1" << endl;
node->next = currNode->next;
currNode->next = node;
list_c->length++;
if (pos == list_c->length)//如果是最后一个结点
{
node->next = list_c->next;//改变最后一个节点的指针域为指向第一个结点
}
}
//delete node; //这里4行释放内存的语句加进去,也报错读取访问冲突。
//node = NULL;
//delete currNode;
//currNode->next = NULL;
} 菜鸟小乔 发表于 2019-6-1 17:03
下面这段插入功能的函数,node是在这个函数里定义的,难道它不是局部变量吗?
学C/C++的还是要了解一下栈内存和堆内存还有指针,node是局部变量没错了,但是你delete node / free(node)操作的是node本身吗???????????????=====>你操作的是node指向的地址,不是node变量本身!! 菜鸟小乔 发表于 2019-6-1 17:03
下面这段插入功能的函数,node是在这个函数里定义的,难道它不是局部变量吗?
另外局部变量会自动销毁,就更加用不着释放了 怎么老是你{:10_327:} 我就是个弟弟 发表于 2019-6-1 18:29
怎么老是你
{:9_240:}因为初学,每天都遇到各种问题。。。 本帖最后由 我就是个弟弟 于 2019-6-1 18:50 编辑
菜鸟小乔 发表于 2019-6-1 18:45
因为初学,每天都遇到各种问题。。。
void Print(C_LinkList *list_c)
{
if (list_c->length == 0 || list_c->next == NULL)
{
cout << "链表为空,无内容可打印!" << endl;
list_c->length = 0;
return;
}
Node* node = new Node;
node->next = NULL;
node = list_c->next; //创建临时结点第一个结点开始遍历
for (int i = 0; i < list_c->length; i++)
{
cout << node->data.id << ":" << node->data.name << endl;
node = node->next;
}
//delete node; //添加delete就会报错,访问冲突。
//node = NULL;
cout << "*****打印结束*******" << endl;
}
Node* node = new Node;
node->next = NULL;
node = list_c->next; //创建临时结点第一个结点开始遍历
这一段有错误吧
刚刚申请的内存就没有指针指向了,
应该写成
Node *node = nullptr; 才对吧
你这个node就是想顺着链表走一遍是吧,你就直接Node *node = nullptr; 就行了
要不然const Node *node = nullptr;这样好一些。 Krant5 发表于 2019-6-1 17:08
学C/C++的还是要了解一下栈内存和堆内存还有指针,node是局部变量没错了,但是你delete node / free(node ...
delete node;这个操作是释放node指向的内存,这个我理解;
但是为什么这里不能直接释放块内存呢?这块内存不就是用来存放一个临时的结点吗,函数都执行完了,这个临时结点也不需要了,为什么不能delete呢? 本帖最后由 菜鸟小乔 于 2019-6-1 19:04 编辑
我就是个弟弟 发表于 2019-6-1 18:48
Node* node = new Node;
node->next = NULL;
没有啊,
Node* node = new Node;//让node指向一块新申请的内存;
node->next = NULL;//因为node里面包含指针域 Node*next,要给这个指针 Node*next赋初值NULL,不然Node*next就成野指针了。
你是不是理解成node=NULL了? 程序运行是要装载到内存中的。 内存不是一坨浆糊是有人为(操作系统)划分的
程序中有的变量时存放在栈中的,有的变量时存放在自由存储区(堆)中的,函数中声明定义的变量都是存放在栈中的
C++中使用new 申请的内存时从自由存储区中申请的内存。
栈中的数据不能使用delete回收,
栈中的数据,不是回收,而是栈顶指针覆盖。(CPU老子很忙的,没时间把一堆零写道内存中)
弟弟的小小见解 我就是个弟弟 发表于 2019-6-1 19:04
程序运行是要装载到内存中的。 内存不是一坨浆糊是有人为(操作系统)划分的
程序中有的变量时存放在栈中 ...
new出来的是node指向的堆内存,我现在就是想要释放这个堆内存,难道delete node执行的不是这个操作吗?
我要晕了。。。{:10_243:} 本帖最后由 我就是个弟弟 于 2019-6-1 19:11 编辑
菜鸟小乔 发表于 2019-6-1 18:59
没有啊,
Node* node = new Node;//让node指向一块新申请的内存;
node->next = NULL;//因为node ...
Node* node = new Node;
node->next = NULL;
node = list_c->next; //创建临时结点第一个结点开始遍历
不是,你再解释一遍,你是不是对指针有什么误解。
指针的初始化时指针的初始化,
Node的初始化时Node的事情。
指针指向的时地址,地址呀。 菜鸟小乔 发表于 2019-6-1 19:08
new出来的是node指向的堆内存,我现在就是想要释放这个堆内存,难道delete node执行的不是这个操作吗?
...
哈哈哈,晕就对了,第一次都晕。{:10_327:} 我就是个弟弟 发表于 2019-6-1 19:08
不是,你再解释一遍,你是不是对指针有什么误解。
指针的初始化时指针的初始化,
Node的初始化时No ...
Node是一个结点的数据类型,结点本身就包含了一个指向下一节点的指针next,所以初始化node,还要初始化它所包含的node->next。前两句是创建了一个空的结点,第三句把链表第一个结点赋给这个空结点。{:10_251:}{:10_247:} 菜鸟小乔 发表于 2019-6-1 18:53
delete node;这个操作是释放node指向的内存,这个我理解;
但是为什么这里不能直接释放块内存呢?这块 ...
你的变量是临时的,可是链表里面的空间并不是.你把new出来的节点直接接插入链表,即该地址以后还会用,所以不能delete 本帖最后由 菜鸟小乔 于 2019-6-2 13:30 编辑
Krant5 发表于 2019-6-1 20:29
你的变量是临时的,可是链表里面的空间并不是.你把new出来的节点直接接插入链表,即该地址以后还会用,所以 ...
哦~好像理解了~{:7_113:}多谢大神指点~~~
PS:不好意思啊,我级别太低,还没有权限添加好友。。。尴尬。{:10_243:}
页:
[1]