为什么我使用 std::copy() 收到运行时错误(分段错误)?

Why do I receive Runtime Error(Segmentation fault) by using std::copy()?

本文关键字:运行时错误 分段 错误 std copy 为什么      更新时间:2023-10-16

我正在写一个家庭作业程序。

这是关于模拟两个人玩纸牌游戏。

起初,Y先生有n张牌,而P先生有m张牌,他们拥有的牌是独一无二的。

Y先生先玩,以下是你玩游戏的方式:

  • 首先,你选择一个数字x,如果这个数字在你的竞争对手的牌中,你就拿走它。
  • 然后,如果你已经有了你得到的卡,你把你手上的牌和你刚刚得到的牌都扔掉。
  • 然后,你的竞争对手做同样的事情(他选择一个数字w(。

第一轮到此结束。

当其中一个人用完牌时,游戏结束。

此外,如果游戏没有在k回合内结束,它会自动结束。

程序必须输出:

一个数字l,表示游戏将在多少回合内结束。

Y先生和P先生在一轮结束时的牌。

我尝试使用矢量模拟游戏,但是当我尝试执行它时,代码会引发分割错误。

这是我的代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,k,w,x,a;
vector<int> y,p;
vector<vector<int>> ymoves;
vector<vector<int>> pmoves;
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>a;
y.push_back(a);
}
for(int i=0;i<m;i++){
cin>>a;
y.push_back(a);
}
cin>>k;
bool b=1;
for(int i=0;i<k;i++){
cin>>x>>w;
for(int j=0;j<p.size();j++){
if(p[j]==x){
y.push_back(x);
p.erase(p.begin()+j);
break;
}
}
for(int j=0;j<y.size()-1;j++){
if(y[j]==x){
y.erase(y.begin()+j);
y.pop_back();
break;
}
}
for(int j=0;j<y.size();j++){
if(y[j]==w){
p.push_back(w);
y.erase(y.begin()+j);
break;
}
}
for(int j=0;j<p.size()-1;j++){
if(p[j]==w){
p.erase(p.begin()+j);
p.pop_back();
break;
}
}
copy(y.begin(),y.end(),ymoves[i].begin());
copy(p.begin(),p.end(),pmoves[i].begin());
if(y.empty()||p.empty()){
b=0;
cout<<i<<'n';
for(int j=0;j<i;j++){
cout<<ymoves[j].size()<<' ';
for(int l=0;l<ymoves[j].size();l++)cout<<ymoves[j].at(l)<<' ';
cout<<'n';
cout<<pmoves[j].size()<<' ';
for(int l=0;l<pmoves[j].size();l++)cout<<pmoves[j].at(l)<<' ';
cout<<'n';
}
break;
}
}
if(b){
cout<<k<<'n';
for(int j=0;j<k;j++){
cout<<ymoves[j].size()<<' ';
for(int l=0;l<ymoves[j].size();l++)cout<<ymoves[j].at(l)<<' ';
cout<<'n';
cout<<pmoves[j].size()<<' ';
for(int l=0;l<pmoves[j].size();l++)cout<<pmoves[j].at(l)<<' ';
cout<<'n';
}
}
}

一个会导致未定义行为的问题,并且可能随时导致分段错误:

copy(y.begin(), y.end(), ymoves[i].begin());
copy(p.begin(), p.end(), pmoves[i].begin());

ymovespmoves都初始化为0大小。因此,执行ymoves[i]/pmoves[i]会导致越界访问,从而导致 UB。

当您全局定义ymovespmoves时(这在您的情况下没有多大意义,通常应该避免(,一旦您知道k有多大,就需要使用 resize((:

cin>>k;
ymoves.resize(k);
pmoves.resize(k);

但这仍然会导致在您执行copy点时出现未定义的行为。由于存储在pmoves/ymoves中的vecotr也以0的大小进行初始化,但是如果您使用copy则必须确保目标足够大以容纳数据。

因此,您需要对以下各项进行resize

ymoves[i].resize(y.size());
pmoves[i].resize(p.size());
copy(y.begin(),y.end(),ymoves[i].begin());
copy(p.begin(),p.end(),pmoves[i].begin());

但我不确定在这里做copy是否正确,我不知道覆盖现有值是否是您想要做的。

另外两个错误是:for(int j=0;j<p.size()-1;j++){for(int j=0;j<y.size()-1;j++){size()返回一个有符号值,所以如果p.size()0你就会遇到问题,这正是代码中发生的情况。仅当p.size()不为零时,才应执行这些循环。

但是由于变量的命名不是最佳的,因此很难确定该部分是否正确以及是否有更多部分存在问题。但这至少是导致UB的最明显原因。