我用vs2015运行,会在析构函数那里报错:
“引发了异常: 读取访问权限冲突。”
下面是我把出问题的地方提出来重写的
class Test
{
public:
Test() :next(NULL) { a++; }
~Test()
{
Test *i = next;
while (i)
{
next = i->next;
delete i;
i = next;
}
}
void alloc(size_t num)
{
Test *head = new Test;
next = head;
for (int i = 0; i < num - 1; ++i)
{
head->next = new Test;
head = head->next;
}
head = NULL;
}
Test* next;
static int a;
};
int Test::a = 0;
int main()
{
Test *t = new Test;
t->alloc(5);
delete t; // err
return 0;
}
我看见网上有类似的代码:
一个高效的内存池实现 - 厚积薄发 - C++博客 http://www.cppblog.com/weiym/archive/2012/05/05/173785.html
13 个解决方案
#1
程序是有问题的,
删除内存的时候,应该从链表尾巴开始 一个个删除。
你现在的做法,删除第一个test的时候,会试图删除整个链表,
但是删除到第二个节点的时候,他的析构函数会把第二个节点以及之后的链表都删除掉了,
即,一个节点会被删除多次。因此,出问题。
而且,现在这么设计怪怪的,但是怎么设计更好一时也说不出来的。
删除内存的时候,应该从链表尾巴开始 一个个删除。
你现在的做法,删除第一个test的时候,会试图删除整个链表,
但是删除到第二个节点的时候,他的析构函数会把第二个节点以及之后的链表都删除掉了,
即,一个节点会被删除多次。因此,出问题。
而且,现在这么设计怪怪的,但是怎么设计更好一时也说不出来的。
#2
这样递归了, 直接终止就行,
~Test()
{
if(next)
delete next;
}
#3
我开始也是这个感觉:从表头开始析构不会重复析构吗?但是我设置了if()判断后还是有这个问题。但是书上这么写的,我也没有经验,所以接下去不知道怎么办了。
#4
好像可以,能帮我看看源码吗?vs不怎么会用,vs给的信息很多,但是太多了,看不出问题。 就看下有没有内存泄露就行
#5
崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处,看不懂时双击下一行,直到能看懂为止。
#6
#include <iostream>
using namespace std;
class Test
{
public:
Test() :next(NULL)
{
a++;
}
~Test()
{
Test *i = next;
while (i)
{
Test *temp = i->next;
delete temp;
temp = NULL;
i = next;
}
}
void alloc(size_t num)
{
Test *head = new Test;
next = head;
for (int i = 0; i < num - 1; ++i)
{
head->next = new Test;
head = head->next;
}
head = NULL;
}
Test* next;
static int a;
};
int Test::a = 0;
int main()
{
Test *t = new Test;
t->alloc(5);
delete t; // err
return 0;
}
using namespace std;
class Test
{
public:
Test() :next(NULL)
{
a++;
}
~Test()
{
Test *i = next;
while (i)
{
Test *temp = i->next;
delete temp;
temp = NULL;
i = next;
}
}
void alloc(size_t num)
{
Test *head = new Test;
next = head;
for (int i = 0; i < num - 1; ++i)
{
head->next = new Test;
head = head->next;
}
head = NULL;
}
Test* next;
static int a;
};
int Test::a = 0;
int main()
{
Test *t = new Test;
t->alloc(5);
delete t; // err
return 0;
}
#7
不行,
#8
#include "stdafx.h"
#include <stdlib.h>
#include<stdio.h>
#include<string>
#include <iostream>
struct Node
{
Node* next;
int a;
};
class Test
{
public:
Test() :Head(NULL) { }
~Test()
{
Node *i = Head;
while (i)
{
Head = i->next;
delete i;
i = Head;
}
}
void alloc(size_t num)
{
Head = new Node;
Node* P = Head;
for (int i = 0; i < num - 1; ++i)
{
P->next = new Node;
P = P->next;
}
P->next = NULL;
}
Node* Head;
};
int _tmain(int argc, _TCHAR* argv[])
{
Test *t = new Test;
t->alloc(5);
delete t; // err
return 0;
}
你这个代码写的实在是有问题啊
每个对象会调用析构函数
你这样会重复释放Test
也就是Test 会被释放多次~~~
你能不报内存错误不?
#include <stdlib.h>
#include<stdio.h>
#include<string>
#include <iostream>
struct Node
{
Node* next;
int a;
};
class Test
{
public:
Test() :Head(NULL) { }
~Test()
{
Node *i = Head;
while (i)
{
Head = i->next;
delete i;
i = Head;
}
}
void alloc(size_t num)
{
Head = new Node;
Node* P = Head;
for (int i = 0; i < num - 1; ++i)
{
P->next = new Node;
P = P->next;
}
P->next = NULL;
}
Node* Head;
};
int _tmain(int argc, _TCHAR* argv[])
{
Test *t = new Test;
t->alloc(5);
delete t; // err
return 0;
}
你这个代码写的实在是有问题啊
每个对象会调用析构函数
你这样会重复释放Test
也就是Test 会被释放多次~~~
你能不报内存错误不?
#9
t->alloc(5);
你把你的参数才成0 或者1 你就知道为什么会这样呢~~~~
你把你的参数才成0 或者1 你就知道为什么会这样呢~~~~
#10
你可以参考一下 链表~~~数据结构~~~
哥们~~~
哥们~~~
#11
假设你对象分别为A B C D E 四个对象, 当你析构第一个对象A时, A的析构函数里尝试在while里依次delete B C D E, delete操作又会调用 B C D E的析构函数, 那么在 B C D E 里同样会调用while循环,造成重复删除,并且你删除的时候存在野指针,同样触发异常
#12
在test类内调用alloc函数分配内存,该内存存储的是test类型变量,析构的时候每个test对象都会调用析构函数来释放该这个next链表,最后会重复释放造成程序异常退出。
建议你在释放时加一条if(i==this)来判断释放可以释放
建议你在释放时加一条if(i==this)来判断释放可以释放
#13
谢谢楼上的帮助,
果然还是 delete 这出了问题,可能是作者使用的编译器更高级一点吧,会自动辨别内存类型,
因为中间开辟内存的时候是根据大小开的,用的是 (T*)new char[size],我的例子里没体现出来,
最后把析构改成这样,看上去是解决问题了:
果然还是 delete 这出了问题,可能是作者使用的编译器更高级一点吧,会自动辨别内存类型,
因为中间开辟内存的时候是根据大小开的,用的是 (T*)new char[size],我的例子里没体现出来,
最后把析构改成这样,看上去是解决问题了:
~Test()
{
/*if (next)
delete next;*/
Test *i = next;
while (i)
{
next = i->next;
//delete[] (char*)(i);
delete[] reinterpret_cast<char*>(i);
i = next;
}
}
#1
程序是有问题的,
删除内存的时候,应该从链表尾巴开始 一个个删除。
你现在的做法,删除第一个test的时候,会试图删除整个链表,
但是删除到第二个节点的时候,他的析构函数会把第二个节点以及之后的链表都删除掉了,
即,一个节点会被删除多次。因此,出问题。
而且,现在这么设计怪怪的,但是怎么设计更好一时也说不出来的。
删除内存的时候,应该从链表尾巴开始 一个个删除。
你现在的做法,删除第一个test的时候,会试图删除整个链表,
但是删除到第二个节点的时候,他的析构函数会把第二个节点以及之后的链表都删除掉了,
即,一个节点会被删除多次。因此,出问题。
而且,现在这么设计怪怪的,但是怎么设计更好一时也说不出来的。
#2
这样递归了, 直接终止就行,
~Test()
{
if(next)
delete next;
}
#3
我开始也是这个感觉:从表头开始析构不会重复析构吗?但是我设置了if()判断后还是有这个问题。但是书上这么写的,我也没有经验,所以接下去不知道怎么办了。
#4
好像可以,能帮我看看源码吗?vs不怎么会用,vs给的信息很多,但是太多了,看不出问题。 就看下有没有内存泄露就行
#5
崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处,看不懂时双击下一行,直到能看懂为止。
#6
#include <iostream>
using namespace std;
class Test
{
public:
Test() :next(NULL)
{
a++;
}
~Test()
{
Test *i = next;
while (i)
{
Test *temp = i->next;
delete temp;
temp = NULL;
i = next;
}
}
void alloc(size_t num)
{
Test *head = new Test;
next = head;
for (int i = 0; i < num - 1; ++i)
{
head->next = new Test;
head = head->next;
}
head = NULL;
}
Test* next;
static int a;
};
int Test::a = 0;
int main()
{
Test *t = new Test;
t->alloc(5);
delete t; // err
return 0;
}
using namespace std;
class Test
{
public:
Test() :next(NULL)
{
a++;
}
~Test()
{
Test *i = next;
while (i)
{
Test *temp = i->next;
delete temp;
temp = NULL;
i = next;
}
}
void alloc(size_t num)
{
Test *head = new Test;
next = head;
for (int i = 0; i < num - 1; ++i)
{
head->next = new Test;
head = head->next;
}
head = NULL;
}
Test* next;
static int a;
};
int Test::a = 0;
int main()
{
Test *t = new Test;
t->alloc(5);
delete t; // err
return 0;
}
#7
不行,
#8
#include "stdafx.h"
#include <stdlib.h>
#include<stdio.h>
#include<string>
#include <iostream>
struct Node
{
Node* next;
int a;
};
class Test
{
public:
Test() :Head(NULL) { }
~Test()
{
Node *i = Head;
while (i)
{
Head = i->next;
delete i;
i = Head;
}
}
void alloc(size_t num)
{
Head = new Node;
Node* P = Head;
for (int i = 0; i < num - 1; ++i)
{
P->next = new Node;
P = P->next;
}
P->next = NULL;
}
Node* Head;
};
int _tmain(int argc, _TCHAR* argv[])
{
Test *t = new Test;
t->alloc(5);
delete t; // err
return 0;
}
你这个代码写的实在是有问题啊
每个对象会调用析构函数
你这样会重复释放Test
也就是Test 会被释放多次~~~
你能不报内存错误不?
#include <stdlib.h>
#include<stdio.h>
#include<string>
#include <iostream>
struct Node
{
Node* next;
int a;
};
class Test
{
public:
Test() :Head(NULL) { }
~Test()
{
Node *i = Head;
while (i)
{
Head = i->next;
delete i;
i = Head;
}
}
void alloc(size_t num)
{
Head = new Node;
Node* P = Head;
for (int i = 0; i < num - 1; ++i)
{
P->next = new Node;
P = P->next;
}
P->next = NULL;
}
Node* Head;
};
int _tmain(int argc, _TCHAR* argv[])
{
Test *t = new Test;
t->alloc(5);
delete t; // err
return 0;
}
你这个代码写的实在是有问题啊
每个对象会调用析构函数
你这样会重复释放Test
也就是Test 会被释放多次~~~
你能不报内存错误不?
#9
t->alloc(5);
你把你的参数才成0 或者1 你就知道为什么会这样呢~~~~
你把你的参数才成0 或者1 你就知道为什么会这样呢~~~~
#10
你可以参考一下 链表~~~数据结构~~~
哥们~~~
哥们~~~
#11
假设你对象分别为A B C D E 四个对象, 当你析构第一个对象A时, A的析构函数里尝试在while里依次delete B C D E, delete操作又会调用 B C D E的析构函数, 那么在 B C D E 里同样会调用while循环,造成重复删除,并且你删除的时候存在野指针,同样触发异常
#12
在test类内调用alloc函数分配内存,该内存存储的是test类型变量,析构的时候每个test对象都会调用析构函数来释放该这个next链表,最后会重复释放造成程序异常退出。
建议你在释放时加一条if(i==this)来判断释放可以释放
建议你在释放时加一条if(i==this)来判断释放可以释放
#13
谢谢楼上的帮助,
果然还是 delete 这出了问题,可能是作者使用的编译器更高级一点吧,会自动辨别内存类型,
因为中间开辟内存的时候是根据大小开的,用的是 (T*)new char[size],我的例子里没体现出来,
最后把析构改成这样,看上去是解决问题了:
果然还是 delete 这出了问题,可能是作者使用的编译器更高级一点吧,会自动辨别内存类型,
因为中间开辟内存的时候是根据大小开的,用的是 (T*)new char[size],我的例子里没体现出来,
最后把析构改成这样,看上去是解决问题了:
~Test()
{
/*if (next)
delete next;*/
Test *i = next;
while (i)
{
next = i->next;
//delete[] (char*)(i);
delete[] reinterpret_cast<char*>(i);
i = next;
}
}