C++ 包含链表的链表导致堆损坏错误:为什么?
长话短说:我制作了一个模板双链接列表,将列表放在其他列表中会导致问题。这个问题已经解决了 我正在将双链表作为模板进行测试,遇到了一个问题,将链表放在另一个链表中会出现以下错误: (Microsoft Visual Studio 2010 Express) Windows已在linkListTesting.exe中触发断点。今年五月 可能是由于堆损坏,这表明 linkListTesting.exe或其加载的任何DLL。这也可能是 由于用户在linkListTesting.exe具有焦点时按F12。这个 输出窗口可能有更多诊断信息 搜索这个特定的错误会产生如下结果:“确保不要使用未初始化的变量”-在这种情况下,当我告诉列表向后推/向前推等时,它应该为我初始化列表。 (不按F12键,因此该场景已结束。) 这是我的主要cpp->C++ 包含链表的链表导致堆损坏错误:为什么?,c++,list,memory,linked-list,heap,C++,List,Memory,Linked List,Heap,长话短说:我制作了一个模板双链接列表,将列表放在其他列表中会导致问题。这个问题已经解决了 我正在将双链表作为模板进行测试,遇到了一个问题,将链表放在另一个链表中会出现以下错误: (Microsoft Visual Studio 2010 Express) Windows已在linkListTesting.exe中触发断点。今年五月 可能是由于堆损坏,这表明 linkListTesting.exe或其加载的任何DLL。这也可能是 由于用户在linkListTesting.exe具有焦点时按F12。
#include "vcLLMK2.h"
int main(int argc, char *argv[])
{
vcList<vcList<int>> a;
vcList<int> b;
b.push_back(1);
a.push_back(b);
//ERROR HAPPENS HERE APPARENTLY
return 0;
}
#包括“vcLLMK2.h”
int main(int argc,char*argv[])
{
VCA清单;
VCB清单;
b、 推回(1);
a、 推回(b);
//这里显然发生了错误
返回0;
}
将新条目(在本例中为“1”)向后推(或向前推)到“b”中效果很好。没有碰撞,没有愚蠢。将“b”按入“a”会导致应用程序抛出上述错误,触发断点,然后死亡
我最近开始使用SDL,并打算使用一个列表作为16层的容器,基本上是要渲染的精灵/瓷砖/等的列表。思维方式是,程序将迭代包含层列表中的每个条目,然后在继续下一个之前渲染包含层中的每个对象
“为什么不直接使用std::list?”
-因为那是欺骗
虽然在这篇文章中回答问题的人很可能会指出我的列表结构和实现中的每一个我完全不知道的明显缺陷,但我最关心的是,是什么导致了这个特殊错误,以及如何纠正它。也就是说,我的问题是我构建的链表设置有什么问题导致上述cpp在运行时出错?
下面的链表结构是阅读以下页面的高潮:
将其转换为模板主要是对该页面进行创造性解释的结果:
这是我的链接列表模板类,有很多评论->
#pragma once
#ifndef vcLLMK2_H_INCLUDED
#define vcLLMK2_H_INCLUDED
#define NULL 0
//THIS IS ALL OUR NODE SHOULD EVER NEED
template <class T>
struct vcListNode
{
public:
T data;
vcListNode<T> *next;
vcListNode<T> *prev;
};
template <class T>
struct vcList
{
public:
vcListNode<T> *root;//the list's "start"
vcListNode<T> *end;//the list's "end"
vcListNode<T> *cur;//used to bounce around amongst entries
int size();//returns number of non-null entries
int count;//because keeping track of these is easier than iterating through every time
void setAt(T,int);//sets data in a node
void push_front(T);//inserts a new node at the beginning of the list
void push_back(T);//same thing but back of list
void removeAt(int);//kills a node at an arbitrary spot in the list
void clear();//deletes all of the nodes in the list
T getAt(int);//returns data from a node in the list
vcList<T>& operator = (const vcList<T>&);//used for setting list a's contents to list b
//EDIT COPYCONSTRUCTOR
vcList<T>(const vcList<T>&);//copyconstructor
vcList();// : root(NULL),end(root),cur(NULL),count(0){};
~vcList();
};
//constructor - sets everything to null and count to zero on init
template <class T>
vcList<T>::vcList()
{
root=NULL;
cur=NULL;
end=NULL;
count=0;
}
//destructor - deletes all nodes
template <class T>
vcList<T>::~vcList()
{
clear();
}
//deletes all nodes from root to end
template <class T>
void vcList<T>::clear()
{
if(root==NULL)//assume list has nothing in it, abort
return;
//set current targeted entry to root
cur = root;
//as long as we have somewhere to go...
while(cur->next!=NULL)
{
//go there
cur=cur->next;
//and destroy where we were
delete cur->prev;
}
//then destroy ourselves because nihilism is good for memory
delete cur;
}
//used to set the contents of a list equal to those of another
template <class T>
vcList<T>& vcList<T>::operator= (const vcList<T> &fays)
{
//for starters, clear ourselves of any unwanted garbagedata
clear();
//check the import list's root entry
cur = fays.root;
//if the list containing the values we are importing is empty, we're done, move along
if(cur==NULL)
return *this;
//otherwise, make a new node - it's our new root
vcListNode<T> *newEntry = new vcListNode<T>;
newEntry->data = fays.root->data;
newEntry->prev = NULL;
newEntry->next = NULL;
//set root/end to the new entry
root = newEntry;
end = newEntry;
//update our count
count=1;
//fire through the import-list's entries
//cur starts at root
while(cur->next!=NULL)//(count<fays.count)
{
//move to next entry
cur=cur->next;
//add it to our list, push_back should update the location of 'end' for us
push_back(cur->data);
}
//we should be done here, so go ahead and return everything
return *this;
}
//this is mostly for convenience
template <class T>
int vcList<T>::size()
{
return count;
}
//adds a new entry to the front of our linked list
template <class T>
void vcList<T>::push_front(T info)
{
//eat some memory
vcListNode<T> *newEntry;
newEntry = new vcListNode<T>;
//set our memory and all that neat stuff
newEntry->data = info;
newEntry->next = root;
newEntry->prev = NULL;
//if our linked list is not empty
if(root!=NULL)
//set root's previous link to point at our new entry
root->prev = newEntry;
//if our linked list does not have an assigned end yet
if(end==NULL)
//assume it's empty and set end to our entry
end=newEntry;
//update the position of our root in the list, the beginning now begins at the beginning again
root = newEntry;
//and since we added something to the list, we should probably update our count of things in the list
count++;
}
//this finds an element in the pointer-chain and sets its information
template <class T>
void vcList<T>::setAt(T info,int index)
{
//set our target to the root
cur=root;
//run through the list's entries until we're where we're supposed to be
while(index>0)
{
cur=cur->next;
index--;
}
//set the data in the cell/node/whatever to our input
cur->data=info;
}
//returns the data contained in a node at a position in the list
template <class T>
T vcList<T>::getAt(int meBro)
{
//set target to root
cur=root;
//progress through the list
while(meBro>0)
{
cur=cur->next;
meBro--;
}
//dig the data out of the entry and return it
return cur->data;
}
//adds an element-containing node to the end of the list-chain
template <class T>
void vcList<T>::push_back(T info)
{
//if our list already has entries, end shouldn't be null
if(end!=NULL)
//so just target our end slot
cur=end;
//if our list is empty, however
else
//target the root instead
cur=root;
//create our new node, put stuff in it, etc
vcListNode<T> *newEntry;
newEntry = new vcListNode<T>;
newEntry->data = info;
//we're adding to the END of the list so make next null
newEntry->next = NULL;
//if cur is NOT null, then theoretically we're pointed at the end of the list
if(cur!=NULL)
//set our new entry's previous pointer to the end
newEntry->prev = cur;
//cur IS null, which means the list is empty
else
//set our entry's previous pointer to be null, duh
newEntry->prev = NULL;
//if the end of our list exists
if(end!=NULL)
{
//set the next entry in the list to point at our new entry
end->next = newEntry;
//then set end to target the new entry
end=newEntry;
}
//and if our list does not have an end yet for some reason (read as: it's empty)
else
{
//set the root to our new entry
root = newEntry;
//set the end to our new entry as well, since there's only one entry in the list
end = newEntry;
}
//update count of number of objects in list
count++;
}
//this deletes/removes/destroys/obliterates a node at a location in the list
template <class T>
void vcList<T>::removeAt(int index)
{
//for starters - is what we're trying to kill even here?
if(index>=count)
//NOPE GET OUT
return;
//later on it might speed things up to check whether the distance from end or root is shorter
//for now, just start at the beginning
//target the root
cur=root;
//move through the list to the specified entry
while(index>0)
{
index--;
cur=cur->next;
}
//if the previous entry exists
if(cur->prev!=NULL)
//point its next at the entry after this one
cur->prev->next=cur->next;
//if the previous entry is NULL, it means we're at the root
//so tell root to scoot forward one entry
//if there's a forward to scoot to
else if(cur->next != NULL)
root = cur->next;
//if the next entry exists
if(cur->next!=NULL)
//set the next entry's previous pointer to point at the entry before the targeted one
cur->next->prev=cur->prev;
//if the next entry does not exist, we must be at the end of the list
//so tell the end of the list to scoot back one slot
//if there's a back-one-slot to go to
else if(cur->prev!=NULL)
end = cur->prev;
//remove the entry at the targeted location
delete cur;
//decrement our count
count--;
}
//EDIT -> Copy Constructor
//copy constructor, similar as suggested to the operator=
template <class T>
vcList<T>::vcList(const vcList<T>& fays)
{
//might not be completely necessary, but we're not hurting anything by making sure
clear();
//check the import list's root entry
cur = fays.root;
//if the list containing the values we are importing is empty, we're done, move along
if(cur==NULL)
return;//just return, constructors don't get return types
//otherwise, make a new node - it's our new root
vcListNode<T> *newEntry = new vcListNode<T>;
newEntry->data = fays.root->data;
newEntry->prev = NULL;
newEntry->next = NULL;
//set root/end to the new entry
root = newEntry;
end = newEntry;
//update our count
count=1;
//fire through the import-list's entries
//cur starts at root
while(cur->next!=NULL)//(count<fays.count)
{
//move to next entry
cur=cur->next;
//add it to our list, push_back should update the location of 'end' for us
push_back(cur->data);
}
//we should be done here, so go ahead and return everything
//return *this;
}
#endif
#pragma一次
#如果不包括vcLLMK2
#定义包含的vcLLMK2_H_
#定义空0
//这就是我们的节点所需要的一切
模板
结构vcListNode
{
公众:
T数据;
vcListNode*下一步;
vcListNode*prev;
};
模板
结构vcList
{
公众:
vcListNode*root;//列表的“开始”
vcListNode*end;//列表的“end”
vcListNode*cur;//用于在条目之间来回跳转
int size();//返回非空项的数目
int count;//因为跟踪这些比每次迭代都要容易
void setAt(T,int);//设置节点中的数据
void push_front(T);//在列表的开头插入一个新节点
void push_back(T);//同样的东西,但在列表后面
void removeAt(int);//在列表中的任意位置杀死节点
void clear();//删除列表中的所有节点
T getAt(int);//从列表中的节点返回数据
vcList&operator=(const vcList&);//用于将列表a的内容设置为列表b
//编辑复制构造函数
vcList(const vcList&);//copyconstructor
vcList();/:root(NULL)、end(root)、cur(NULL)、count(0){};
~vcList();
};
//构造函数-在init上将所有内容设置为null,并将计数设置为零
模板
vcList::vcList()
{
root=NULL;
cur=NULL;
end=NULL;
计数=0;
}
//析构函数-删除所有节点
模板
vcList::~vcList()
{
清除();
}
//从根到端删除所有节点
模板
void vcList::clear()
{
如果(root==NULL)//假设列表中没有任何内容,则中止
返回;
//将当前目标项设置为root
cur=根;
//只要我们还有地方去。。。
while(cur->next!=NULL)
{
//去那里
cur=cur->next;
//摧毁我们的家园
删除cur->prev;
}
//然后摧毁我们自己,因为虚无主义有利于记忆
删除cur;
}
//用于将列表的内容设置为与其他列表的内容相同
模板
vcList和vcList::operator=(const vcList和fays)
{
//首先,清除我们自己不想要的垃圾
清除();
//检查导入列表的根条目
cur=fays.root;
//如果包含我们要导入的值的列表为空,则我们完成了,继续
如果(cur==NULL)
归还*这个;
//否则,创建一个新节点-它是我们的新根
vcListNode*newEntry=新vcListNode;
newEntry->data=fays.root->data;
newEntry->prev=NULL;
newEntry->next=NULL;
//将root/end设置为新条目
根=新条目;
结束=新条目;
//更新我们的计数
计数=1;
//通过导入列表的条目激发
//cur从根开始
而(cur->next!=NULL)/(countnext;
//将其添加到我们的列表中,push_back将为我们更新“end”的位置
向后推(当前->数据);
}
//我们应该在这里完成,所以继续并归还所有东西
归还*这个;
}
//这主要是为了方便
模板
int vcList::size()
{
返回计数;
}
//在链接列表的前面添加一个新条目
模板
无效vcList::推前(T信息)
{
//吃点记忆
vcListNode*新条目;
newEntry=新的vcListNode;
//设置我们的记忆和所有整洁的东西
新建条目->数据=信息;
newEntry->next=root;
newEntry->prev=NULL;
//如果我们的链表不是空的
if(root!=NULL)
//将根的上一个链接设置为点