std::vector erase seg fault

closed account (oGhfSL3A)
I tried a few times to create an example program to show the problem I'm having, but they all worked completely fine. I only seem to get a seg fault when I'm doing specifically this, so apologies for the long code.

It's at line 121, the second time I remove a component. Even when I put a breakpoint there everything seems fine. But it is not. Clearly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <iostream>
#include <vector>

class type{
public:
    type(){}
    virtual ~type(){}
    virtual type* clone()=0;
};

class someType:public type{
private:
    int data;
public:
    someType(){
        data =9;
    }
    ~someType(){}
    type* clone(){
        return new someType(*this);
    }
};

class component{
private:
    unsigned id_;
    type* type_;
public:
    component(unsigned id, type &t): id_(id){
        type_=t.clone();
    }
    unsigned getObjectID() const {
        return id_;
    }
    ~component(){
        delete type_;
    }
    component(const component &original){
        type_=original.type_->clone();
        id_=original.id_;
    }
};

template<typename T>
class gappy{            //e.g. you ask for component 7, but it gives you component 5 because there was no elements 2 & 3 (hence 'gappy')
private:
    std::vector<T> components_;                             //components sequential with gaps
    std::vector<std::pair<unsigned, unsigned> > gaps_;      //gaps not sequential
    int getIndex(unsigned ID){
        unsigned index=ID;
        for(unsigned i=0; i<gaps_.size(); i++){
            if(ID>=gaps_[i].first){
                index-=gaps_[i].second;
            }else{
                if(ID>=gaps_[i].first-gaps_[i].second){     //ID in gap (not here)
                    return -1;                              //for null
                }
            }
        }
        if(index>=components_.size()){
            return -1;                      //not in gap, but ID is higher than any in the vector
        }
        return index;
    }
    int getGapIndex(int ID){
        if(ID>0){
            for(std::vector<std::pair<unsigned, unsigned> >::iterator it=gaps_.begin(); it!=gaps_.end(); it++){
                if(static_cast<unsigned>(ID)<it->first&&static_cast<unsigned>(ID)>it->first-1-it->second){
                    return it-gaps_.begin();                //its in this gap
                }
            }
        }
        return -1;      //not in any gap
    }
public:
    gappy(){}
    ~gappy(){}
    void addComponent(const T& component){
        if(components_.empty()){
            if(component.getObjectID()>0){
                gaps_.push_back(std::make_pair(component.getObjectID(), component.getObjectID())); 
            }
        }else{
            if(component.getObjectID()>components_.back().getObjectID()+1){
                gaps_.push_back(std::make_pair(component.getObjectID(), component.getObjectID()-(components_.back().getObjectID()+1)));
            }
        }
        components_.push_back(component);
    }
    T* getComponent(unsigned ID){
        int componentIndex=getIndex(ID);
        if(componentIndex==-1){
            return nullptr;
        }else{
            return &components_[componentIndex];
        }
    }
    void removeComponent(unsigned ID){
        if(components_.size()>0){
            int i=getIndex(ID);
            if(i!=-1){
                if(static_cast<unsigned>(i)==components_.size()-1){         //at end
                    if(!gaps_.empty()&&gaps_.back().first==ID){             //this component had gap before it (now on end)
                        gaps_.pop_back();                                   //pop it off
                    }
                }else{
                    int before = getGapIndex(ID-1);
                    int after = getGapIndex(ID+1);
                    if(before==-1&&after==-1){                              //no gaps either side
                        gaps_.push_back(std::make_pair(ID+1, 1));           //add a gap
                    }else if(before!=-1&&after!=-1){                        //gaps both sides
                        gaps_[after].second+=gaps_[before].second+1;
                        gaps_.erase(gaps_.begin()+before);                  //merge gaps (+1 for this space)
                    }else if(after!=-1){                                    //gap directly after
                        gaps_[after].second++;
                    }else if(before!=-1){                                   //gap before (gaps_[before].first==ID)
                        gaps_[before].first=ID+1;
                        gaps_[before].second++;
                    }
                }
                components_.erase(components_.begin()+i);
            }
        }
    }
    typename std::vector<T>::iterator begin(){
        return components_.begin();
    }
    typename std::vector<T>::iterator end(){
        return components_.end();
    }
};

int main(){
    someType st;
    gappy<component > components_;
    for(unsigned i=0; i<=30; i++){
        component tComponent(i, st);
        components_.addComponent(tComponent);
    }
    components_.removeComponent(14);
    components_.removeComponent(15);
    components_.removeComponent(12);
    components_.removeComponent(13);
    for(unsigned i=0; i<=30; i++){
        component* tComponent=components_.getComponent(i);
        if(tComponent!=nullptr){
            std::cout<< "component "<<i<<": " << tComponent->getObjectID() << "\n";
        }
    }
    return 0;
}


thanks.
Last edited on
you are missing a proper assignment operator for the `component' class
Topic archived. No new replies allowed.