Reputation: 111
I'm writing a somewhat toy program to get into c++. However I'm having quite a lot of trouble with a segmentation fault at a very specific line in my code. I know that the segmentation fault means I tried to access memort that was not given to my program. The code is (somewhat) as follows(it's actually too big to just copy paste) :
class car {
protected:
int speed;
std::string brand;
public:
car (int s, std::string b):speed(s),brand(b) {
std::cout << "New car has been created" << endl;
}
virtual int is_stopped () {
if (speed==0) return 1;
else return 0;
}
virtual void speed_up () {
speed++;
}
car* clone () {
car* tmp(this);
return tmp;
}
};
class fast_car : public car {
public:
fast_car (int s, std::string b):car(s,b) { }
};
class slow_car : public car {
public:
slow_car (int s, std::string b):car(s,b) { }
};
class highway {
int number_of_cars;
car **first; //There are derived classes from car hence the double pointer
public:
highway (int c, int s, std::string b):number_of_cars(c) {
first = new car*[c];
for (int i=0;i<c/2;i++)
first[i] = new fast_car (s,b);
for (int i=c/2;i<c;i++)
first[i] = new slow_car (s,b);
}
void speed_up () {
int pos;
pos = rand()%number_of_cars; //give me a random number between 0 and number_of_cars;
if (pos!=0) pos--; //We don't want position -1
first[pos]->speed_up ();
clone_fast (first[pos], (number_of_cars - pos - 1)); //the second argument is the remaining array "spots" until the end of the array
}
void clone_fast (car* cur, int rem) {
car* tmp;
for (int i=-;i<=rem;i++)
if ((cur+1)->is_stopped ()) { //Exact line where I get the segmentation fault
tmp = cur->clone ();
cur++;
}
}
};
So there it is. I tried to give you everything I could to recreate the problem. I'll try to solve any further questions. Any help would be greatly appreciated.
Upvotes: 0
Views: 288
Reputation: 6697
I would suggest removing all pointer crap, and use more modern idioms. You can expand on the code below. However, it is unclear to me why you have two derived classes: they have no specific data neither methods, so why ?
class car
{
private:
int speed;
std::string brand;
public:
car (int s, std::string b):speed(s),brand(b)
{
std::cout << "New car has been created" << endl;
}
bool is_stopped ()
{
return speed==0;
}
void speed_up ()
{
speed++;
}
};
class fast_car : public car
{
public:
fast_car (int s, std::string b):car(s,b) {}
};
class slow_car : public car
{
public:
slow_car (int s, std::string b):car(s,b) {}
};
class highway
{
private:
std::vector<std::shared_ptr<car>> v_cars;
public:
highway (int c, int s, std::string b):number_of_cars(c)
{
for (int i=0;i<c/2;i++)
v_cars.push_back( std::make_shared<fast_car>(s,b) );
for (int i=c/2;i<c;i++)
v_cars.push_back( std::make_shared<slow_car>(s,b) );
}
};
int main()
{
highway h( 50, 20 );
return 0;
}
Upvotes: 0
Reputation: 133
The car*
s are created by new
, and aren't necessarily contiguous; they certainly aren't arrays that you can pointer-arithmetic around with. (car*) + 1
is not the same as (car**)[i + 1]
(which is more like (car**) + 1
). You probably want something a bit more like (*(first + 1))->doThing()
, not (first[X] + 1)->doThing()
.
Edit: to be a bit more clear, if you can't do car[X + 1]
, then you can't do *(car + 1)
. Since the car
s in clone_fast()
are object pointers and not arrays, you can't do car[X + 1]
, thus (cur + 1)->is_stopped()
is wrong.
Upvotes: 1