有未经处理的异常: 0xC0000005: 读取位置 0xccccccc0 时发生访问冲突

时间:2021-03-19 19:03:30
每次运行到cout<<(p[i]*p[k]).count(x)时就报错,调试发现p[i]*p[k](求两个集合的交)的返回值的first->link是有值的,但是当它作为参数被count()函数调用时,显示first指针被重新初始化为0xcccccccc,first->link为???,请问问题出在哪?


头文件如下:
template <class T>
struct setnode
{
T data;
setnode<T>*link;
setnode():link(NULL){};
setnode(const T&x,setnode<T>*next=NULL):data(x),link(next){};
};

template<class T>
class linkedset
{
private:
setnode<T>*first,*last;
public:
linkedset(){first=last=new setnode<T>;}
linkedset(linkedset<T>&R);
bool addmember(const T&x);
linkedset<T>&operator+(linkedset<T>&R);
linkedset<T>&operator*(linkedset<T>&R);
linkedset<T>&operator=(linkedset<T>&R);
bool contains(const T x);
int&count(int&x);
};

template<class T>
bool linkedset<T>::contains(const T x)
{
setnode<T>*temp=first->link;
while(temp!=NULL&&temp->data<x)
temp=temp->link;
if(temp!=NULL&&temp->data==x) return true;
else return false;
};

template<class T>
bool linkedset<T>::addmember(const T&x)
{
setnode<T>*p=first->link,*pre=first;
while(p!=NULL&&p->data<x)
{
pre=p;p=p->link;
}
if(p!=NULL&&p->data==x) return false;
setnode<T>*s=new setnode<T>(x);
s->link=p;pre->link=s;
if(p==NULL) last=s;
return true;
};

template<class T>
linkedset<T>&linkedset<T>::operator+(linkedset<T>&R)
{
setnode<T>*pb=R.first->link;
setnode<T>*pa=first->link;
linkedset<T>temp;
setnode<T>*p,*pc=temp.first;
while(pa!=NULL&&pb!=NULL)
{
if(pa->data==pb->data)
{
pc->link=new setnode<T>(pa->data);
pa=pa->link;pb=pb->link;
}
else if(pa->data<pb->data)
{
pc->link=new setnode<T>(pa->data);
pa=pa->link;
}
else
{
pc->link=new setnode<T>(pb->data);
pb=pb->link;
}
pc=pc->link;
}
if(pa!=NULL) p=pa;
else p=pb;
while(p!=NULL)
{
pc->link=new setnode<T>(p->data);
pc=pc->link;p=p->link;
}
pc->link=NULL;temp.last=pc;
return temp;
};

template<class T>
linkedset<T>&linkedset<T>::operator*(linkedset<T>&R)
{
setnode<T>*pb=R.first->link;
setnode<T>*pa=first->link;
linkedset<T>temp;
setnode<T>*pc=temp.first;
while(pa!=NULL&&pb!=NULL)
{
if(pa->data==pb->data)
{
pc->link=new setnode<T>(pa->data);
pc=pc->link;
pa=pa->link;
pb=pb->link;
}
else if(pa->data<pb->data) pa=pa->link;
else pb=pb->link;
}
pc->link=NULL;
temp.last=pc;
return temp;
};

template<class T>
linkedset<T>&linkedset<T>::operator=(linkedset<T>&R)
{
setnode<T>*pb=R.first->link;
setnode<T>*pa=first=new setnode<T>;
while(pb!=NULL)
{
pa->link=new setnode<T>(pb->data);
pa=pa->link;
pb=pb->link;
}
pa->link=NULL;
last=pa;
return*this;
};

template<class T>
int&linkedset<T>::count(int&x)
{
x=0;
setnode<T>*p=first->link;
while(p!=NULL)
{
x++;
p=p->link;
}
return x;
}

template<class T>
linkedset<T>::linkedset(linkedset<T>&R)
{
setnode<T>*srcptr=R.first->link;
first=last=new setnode<T>;
while(srcptr!=NULL)
{
last->link=new setnode<T>(srcptr->data);
last=last->link;
srcptr=srcptr->link;
}
last->link=NULL;
};

源文件如下:


int main()
{
int m,n,x,k=-1;
linkedset<int> R;
cout<<"Enter n,m:";
cin>>n>>m;
linkedset<int>*p=new linkedset<int>[m];
for(int i=0;i<m;i++)
{
cout<<"请输入小组"<<i+1<<"的第一个学生(输入-1结束):"<<endl;
cin>>x;
while(x!=-1)
{
p[i].addmember(x);
cout<<"下一个学生:"<<endl;
cin>>x;
}
cout<<"小组"<<i+1<<"有"<<p[i].count(x)<<"个学生"<<endl;
cout<<endl;
}
for(int i=0;i<m;i++)
{
if(p[i].contains(0)==true) k=i;
}
if(k==-1) cout<<"学生0没有参加任何小组,"<<"只有1个嫌疑患者。"<<endl;
else
{
for(int  i=0;i<m&&i!=k;i++){
cout<<(p[i]*p[k]).count(x);
if(R.count(x)!=0) p[k]=(p[i]+p[k]);
}

}
return 0;
}

4 个解决方案

#1


template<class T>
linkedset<T>&linkedset<T>::operator*(linkedset<T>&R)
{
     ....
     linkedset<T>temp;  
     ....
     return temp; ======>>返回local变量,无效的
}
============
template<class T>
linkedset<T> linkedset<T>::operator*(linkedset<T>&R)      // 不能返回引用
{
     ....
     linkedset<T>temp;  
     ....
     return temp;
}

#2


不能返回局部变量,因为局部变量的生命周期结束后就不能作为一个正常的值来引用了。局部变量类型有:定义在局部函数内的变量(void foobar(){int i;}这个i就是个局部变量)

#3


崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。

#4


爆栈爆堆访问野指针(即已释放的指针)都可能引发,你要细查

#1


template<class T>
linkedset<T>&linkedset<T>::operator*(linkedset<T>&R)
{
     ....
     linkedset<T>temp;  
     ....
     return temp; ======>>返回local变量,无效的
}
============
template<class T>
linkedset<T> linkedset<T>::operator*(linkedset<T>&R)      // 不能返回引用
{
     ....
     linkedset<T>temp;  
     ....
     return temp;
}

#2


不能返回局部变量,因为局部变量的生命周期结束后就不能作为一个正常的值来引用了。局部变量类型有:定义在局部函数内的变量(void foobar(){int i;}这个i就是个局部变量)

#3


崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。

#4


爆栈爆堆访问野指针(即已释放的指针)都可能引发,你要细查