从 C++ 中的集合中擦除时出现分段错误

segmentation fault while erasing from a set in c++

本文关键字:分段 错误 擦除 C++ 集合      更新时间:2023-10-16

eq是事件队列,其中每个元素的形式都是e = (F = (int, double(, S = (int, double((。 当我在事件队列中处理事件 e = (F, S( 时,我要么插入或删除,要么从set< pair<int, double> > el插入 e.S。删除e.S时,您可以假设e.S已经在el

。但是,当我尝试通过el.erase(e.S)el中删除e.S时,它会给出错误:

分段错误 11

请帮忙。

#include <iostream>
#include <vector>
#include <cmath>
#include <queue>
#include <climits>
#include <set>
#define MP make_pair
#define PB push_back
#define F first
#define S second
#define OUT cout <<
#define IN cin >>
#define newline cout << "n"
#define space cout << " "
#define fastIO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define PI 3.14159265
#define EPSILON 1e-9
#define OBJ pair<int, double>
#define EVENT pair< OBJ, OBJ >
using namespace std;
struct point {
int x, y;
};
double angle(double x, double y) {
double t = atan2 (y, x) * 180.0 / PI;
return t >= 0 ? t : 360 - fabs(t);
}
vector< struct point > vp;
struct COMP {
bool operator()(const EVENT &p, const EVENT &q) {
if(fabs(p.F.S - q.F.S) > EPSILON) {
return p.F.S < q.F.S;
}
else if(p.F.F != q.F.F) return p.F.F == 0;
else return p.S.S < q.S.S;
}
} comp_eq;
vector< EVENT > eq;
class comp_el {
public:
bool operator()(const OBJ &p, const OBJ &q) {
if(fabs(p.S - q.S) > EPSILON) {
return p.S < q.S;
}
else {
double a_p = angle(vp[p.F].y, vp[p.F].x), a_q = angle(vp[q.F].y, vp[q.F].x);
if(fabs(a_p - a_q) > EPSILON) return a_p < a_q;
else return false;
}
}
};
set< OBJ, comp_el > el;
int main() {
int n, r;
double theta, phi, d, beg, end;
vector<struct point> vp;
struct point p;
while(1) {
IN n;
if(n == 0) break;
eq.clear();
vp.clear();
for(int j = 0; j < n; j++) {
IN p.x;
IN p.y;
IN r;
vp.PB(p);
d = sqrt(p.x * p.x + p.y * p.y);
theta = angle(p.y, p.x);
phi = asin(r/d);
beg = theta - phi;
beg = beg < 0 ? 360 - fabs(beg) : beg;
eq.PB(MP(MP(0, beg), MP(j, d)));
if(fabs(beg - 0) < EPSILON) {
eq.PB(MP(MP(0, 360), MP(j, d)));
eq.PB(MP(MP(1, 360), MP(j, d)));
}
end = beg + 2 * phi;
if(fabs(end - 360) > EPSILON) {
if(end > 360) {
eq.PB(MP(MP(1, 360), MP(j, d)));
eq.PB(MP(MP(0, 0), MP(j, d)));
eq.PB(MP(MP(1, end - 360), MP(j, d)));
}
else eq.PB(MP(MP(1, end), MP(j, d)));
}
else {
eq.PB(MP(MP(1, 360), MP(j, d)));
eq.PB(MP(MP(0, 0), MP(j, d)));
eq.PB(MP(MP(1, 0), MP(j, d)));
}
}
sort(eq.begin(), eq.end(), comp_eq);

//I NEED HELP IN THE PART BELOW.

for(int j = 0; j < eq.size(); j++) {
EVENT e = eq[j];
OUT e.F.F;
space;
OUT e.F.S;
space;
OUT e.S.F;
space;
OUT e.S.S;
space;
newline;
}
double maxD = -INT_MAX;
for(int j = 0; j < eq.size(); j++) {
EVENT e = eq[j];
if(e.F.F == 0) {
el.insert(e.S);
}
else {
el.erase(e.S);
}
set< OBJ >::iterator first = el.begin();
// for(; first != el.end(); first++){
//  OUT (*first).F; space; OUT (*first).S;
// }
// newline;
if(first != el.end()) {
OUT (*first).F;
space;
OUT (*first).S;
newline;
if((*first).S > maxD) maxD = (*first).S;
}
}
OUT maxD;
newline;
}
return 0;
}

comp_el尝试在全局变量vp中查找元素 - 但该向量始终为空。 相反,main()填充一个局部变量,该变量恰好也被命名为vp,但在其他方面与全局vp不同且无关。然后,程序通过访问索引超出边界的向量元素来展示未定义的行为。


另请注意,基于"足够接近"几乎相等(如fabs(p.F.S - q.F.S) > EPSILON(的比较器通常不满足严格弱排序的要求。这种比较器诱导的等价关系不是传递的:可以找到三个元素ABC使得A足够接近BB足够接近C,但A不够接近C