C++ vector segmentation error when accessing the first element - c++

I've been having a really hard time with this error, as I've tried everything I could to fix it to no avail.
I'm building a genetic algorithm for my C++ class and I have to store a lot of individuals in a container of some sort, so I chose to make a custom container class called "GenePool" to hold instances of "IndivPtr" (which is a typedef smart pointer to "Individual").
These individuals are stored in its internal vector, and I overloaded the subscript operator ([]) to access its elements.
However, my program barely runs because after filling the vector with elements, it always causes a segmentation error when trying to access the FIRST element from the vector, and it throws an std::out_of_range exception!
I would like to know in this case how I can access elements from my vectors without causing such error.
Here is the code for GenePool:
#include "GenePool.h"
#include "Controller.h"
#include <algorithm>
GenePool::GenePool()
{
// Default empty constructor
individualList.reserve(10000);
}
GenePool::~GenePool()
{
//deleteAll();
}
void GenePool::sortPool()
{
// Sort the vector from greatest to least using GreatertThanSort
// The third parameter is the address of the GreaterThanSort's greater than function for a GreaterThanSort for Individuals
std::sort(individualList.begin(), individualList.end(), &GreaterThanSort::greaterThan);
}
Individual& GenePool::operator[](int index)
{
// Put exception handling here somewhere (a throw statement)
return *individualList.at(index);
}
// Get an individual from the list between index 0 and index size - 1
Individual& GenePool::getRandIndiv()
{
return this->operator[](Controller::getRandNumInRange(0, this->size() - 1));
}
void GenePool::pushBackIndiv(const IndivPtr& indiv)
{
individualList.push_back(indiv);
}
void GenePool::pushBackIndiv(Individual& indiv)
{
Individual * p2Indiv = &indiv;
if(LangermannPoint * pIndivL = dynamic_cast<LangermannPoint*>(p2Indiv))
{
IndivPtr pL(new LangermannPoint(*pIndivL));
individualList.push_back(pL);
}
else if(CurveParams * pIndivC = dynamic_cast<CurveParams*>(p2Indiv))
{
IndivPtr pC(new CurveParams(*pIndivC));
individualList.push_back(pC);
}
}
int GenePool::size() const
{
return individualList.size();
}
void GenePool::clear()
{
if(!individualList.empty())
{
individualList.clear();
}
}
void GenePool::addContentsOf(GenePool& other)
{
for(int i = 0; i < other.size(); ++i)
{
pushBackIndiv(other[i]);
}
}
Before this subscript is called, the vector is filled:
// Initialize a population of individuals with randomly generated parameters.
if(getProblemType() == Controller::OPTIMIZATION)
{
for(int i = 0; i < getInitPopSize(); ++i)
{
population.pushBackIndiv(IndivPtr(new LangermannPoint(getRandFloatInRange(0.0f, LangermannPoint::POINT_BOUND),
getRandFloatInRange(0.0f, LangermannPoint::POINT_BOUND))));
}
}
else
{
for(int i = 0; i < getInitPopSize(); ++i)
{
population.pushBackIndiv(IndivPtr(new CurveParams(getRandFloatInRange(-CurveParams::PARAM_BOUND, CurveParams::PARAM_BOUND),
getRandFloatInRange(-CurveParams::PARAM_BOUND, CurveParams::PARAM_BOUND),
getRandFloatInRange(-CurveParams::PARAM_BOUND, CurveParams::PARAM_BOUND),
getRandFloatInRange(-CurveParams::PARAM_BOUND, CurveParams::PARAM_BOUND))));
}
}
Here is the invocation to the subscript operator that always crashes:
bool Controller::terminationCondition()
{
population.sortPool();
// After sorting, the first is the fittest
if(generationCount <= 1)
{
setSolution(population[0]);
return false;
}
else if(getSolution() < population[0] && generationCount < MAX_GEN_COUNT)
{
setSolution(population[0]);
return false;
}
else
{
return true;
}
}

First of all, in pushBackIndiv you should add an else for the case of error where it is not LangermannPoint or CurveParams. It seems the problem is not here but you should add that in it will help you.
Second, in operator[](int index), before accessing an element check if the requested index won't give you an out-of-range. You can check this comparing with individualList.size().
Also call size() to see if you actually have elements in the list.

Alright, so it turns out that the real reason why I kept getting this error was because of a silly mistake on my part: I forgot to initialize the size of the population, so it never added elements to the vector when I thought it did.
But thankfully, I learned all about segmentation errors through investigating this error and how to make a vector of abstract data types :)

Related

Getting a runtime error while passing a function

I am writing a function that takes an integer "size" as input and returns a 2d vector which is filled spirally from 1 to size*size. So, I created 4 additional functions to traverse left, right, bottom and top. All functions are working correctly except bottom function. Here, i am providing a part of the whole code that is necessary to resolve the problem.
Error :- Your submission stopped because of a runtime error. ex: division by
zero, array index out of bounds, uncaught exception.
I am getting a runtime error when i am passing a "right" function and a "bottom" function. The problem is in the function but I am unable to resolve it. The right function is passing smoothly but the problem is with the bottom function.
void right(vector<vector<int>> &A,int &row,int &column,int &total_elements,int size)
{
if(total_elements==0) return;
while(A[row][column]==INT_MIN && column<size)
{
A[row][column]=1+A[row][column-1];
column++;
total_elements--;
}
column--;
return;
}
void bottom(vector<vector<int>> &A,int &row,int &column,int &total_elements,int size)
{
if(total_elements==0) return;
while(A[row][column]==INT_MIN && row<l)
{
A[row][column]=1+A[row-1][column];
row++;
total_elements--;
}
row--;
return;
}
vector<vector<int> > Solution::generateMatrix(int size) {
int total_elements=size*size;
vector< vector <int> > arr(size, vector <int> (size, INT_MIN));
arr[0][0]=1;total_elements-=1;
int row=0;
int column=1;
right(arr,row,column,total_elements,size);
row++;
bottom(arr,row,column,total_elements,size);
column--;
return arr;
}

Debug assertion error - List iterators incompatible

I'm working on a program that is supposed to put every Window in a list, resize it, and move it to a screen position according to a specified layout.
When I'm running this function however I get a debug assertion error saying "list iterators incompatible".
Here is the code:
void Control::checkForNewWindows()
{
for (std::list<Window>::iterator i = mainDetector.getWindowList().begin(); i != mainDetector.getWindowList().end(); ++i)
{
bool forBreak = false;
if ((i->getTitle().find("sample_title") != std::string::npos) && (i->getState() == false))
{
for (int y = 0; y < 3; y++)
{
for (int x = 0; x < 4; x++)
{
if (activeLayout.windowLayout[y][x].getHandle() == 0)
{
moveWindow(*i, activeLayout.dimensionsLayout[y][x].x, activeLayout.dimensionsLayout[y][x].y, activeLayout.dimensionsLayout[y][x].width,
activeLayout.dimensionsLayout[y][x].height);
activeLayout.windowLayout[y][x] = *i;
activeLayout.windowLayout[y][x].setState(true);
forBreak = true;
}
if (forBreak)
{
break;
}
}
if (forBreak)
{
break;
}
}
}
}
}
The error occurs during the first for loop, hope someone can help me fix this
Edit:
Here is the getWindowList function:
std::list <Window> Detector::getWindowList()
{
return windowList;
}
and the windowList definition:
std::list <Window> windowList;
Your loop looks like this:
for (std::list<Window>::iterator i = mainDetector.getWindowList().begin();
i != mainDetector.getWindowList().end();
++i)
Given the above, the issue is this:
std::list <Window> Detector::getWindowList()
{
return windowList;
}
You're returning a copy of the list, not the original. Thus the iterator to the copy will be used in the loop and not the iterator of windowList. In fact, you are using two different iterators in the loop construct, and neither one of them refers to the original list, only copies.
The fix is to return a reference:
std::list <Window>& Detector::getWindowList()
{
return windowList;
}
You're now returning a reference to the actual list, not a copy. Now the iterators you are using in the loop constraints refer to the same list, not different lists.
FYI for others researching this, you can also get the same error message when dealing with dangling pointers and deleted memory. I ran across this thread while tracking down that error message. In my case, there was an iterator to a list that had been deleted.

Trouble removing elements from C++ vector

I'm trying to remove 'dead' bullets from my vector of bullets. Every frame, I'm calling the Bullet::update() function which looks like this:
void Bullet::update()
{
for(int i = 0; i != mAmmo.size(); i++)
{
if(mAmmo[i].sprite.getPosition().x > 700)
mAmmo[i].mAlive = false;
if(mAmmo[i].mAlive == false)
{
// I get a Debug Assertion Failed at runtime from this piece of code
mAmmo.erase(mAmmo.begin()+i);
}
if(mAmmo[i].mAlive == true)
{
mAmmo[i].sprite.move(mMovement);
}
}
}
Am I doing this completely incorrectly? This is the first time I've really used vectors more than just following through a tutorial. If I need to post any more code, just tell me. I've been working on this for the past few hours, so I'm a wee bit desperate to get this to work.
Thanks in advance!
You're easily walking into undefined behavior as soon as the ith element is the last element in your list. Use iterators, and pay special attention to the return value of erase(), as it automatically advances the iterator for you so your loop doesn't have to.
void Bullet::update()
{
for (auto it = mAmmo.begin(); it != mAmmo.end();)
{
if(it->sprite.getPosition().x > 700)
it->mAlive = false;
if (!it->mAlive)
{
// erase and get next iterator
it = mAmmo.erase(it);
}
else
{ // move and increment
it->sprite.move(mMovement);
++it;
}
}
}

Null pointers to classes

I was trying to validate pointers in an array so I didn't cause any memory errors,
and this method:
for(int i=0;i<array_size;i++) {
if (array[i]!=NULL)
array[i]->stuff();
}
}
has worked in the past.
Now, I have to do the same thing, except do it all in order based on an object variable.
My new method is:
Direct2Entity* nextset[MAX_ENTS]; // ents[MAX_ENTS] is also a Direct2Entity* array
for(int i=0;i<MAX_ENTS;i++) {
nextset[i]=NULL; // note that ents[] is also flushed before this
}
int nextsetid=0;
int maxn;
bool stillnull;
while(true) { // infinite sorting loop
maxn=-1;
stillnull=true;
for(int i=0;i<next_put;i++) {
if (ents[i]!=NULL) {
stillnull=false;
if (ents[i]->depth<0) { // make sure no infinite loops occur with negative depth
ents[i]->depth=0;
}
if (ents[i]->depth>maxn) {
nextset[nextsetid++]=ents[i];
ents[i]=NULL; // make NULL to further loop
}
}
}
if (stillnull) break;
}
for(int i=0;i<next_put;i++) {
if (nextset[i]!=NULL) {
ents[i]=nextset[i]; // copy nextset[] to ents[]
}
}
for(int i=0;i<next_put;i++) {
if (ents[i]!=NULL) {
if (ents[i]->getroom()==current_room) {
ents[i]->draw(this); // ents[i] is still NULL... ?
}
}
}
In the last for loop, ents[i] was explicitly checked to make sure it would not be dereferencing NULL pointers. Yet C++ goes past it and calls the function. There are all sorts of run time error in all sort of random places, but I am almost sure it is undefined behavior coming from here.
I do not see the logic determining the value of next_put. Is it possible that it simply exceeds the length of ents[]? If so, even if you have properly initialized ents[], when your loop walks off the end of the array, that memory is not initialized (at least as you expect it to be) and your if (ents[i]!=NULL) will be passed (and then your program should crash).

Copy elements of an old array of pointers into new array of pointers?

I need some assistance with a C++ project. What I have to do is remove the given element from an array of pointers. The technique taught to me is to create a new array with one less element and copy everything from the old array into the new one except for the specified element. After that I have to point the old array towards the new one.
Here's some code of what I have already:
I'm working with custom structs by the way...
Data **values = null; // values is initialized in my insert function so it is
// populated
int count; // this keeps track of values' length
bool remove(Data * x) {
Data **newArray = new Data *[count - 1];
for (int i = 0; i < count; i++) {
while (x != values[i]) {
newArray[i] = values[i];
}
count -= 1;
return true;
}
values = newArray;
return false;
}
So far the insert function works and outputs the populated array, but when I run remove all it does is make the array smaller, but doesn't remove the desired element. I'm using the 0th element every time as a control.
This is the output I've been getting:
count=3 values=[5,6,7] // initial insertion of 5, 6, 7
five is a member of collection? 0
count=3 values=[5,6] // removal of 0th element aka 5, but doesn't work
five is a member of collection? 0
count=4 values=[5,6,5] // re-insertion of 0th element (which is stored in
five is a member of collection? 0 // my v0 variable)
Could anyone nudge me in the right direction towards completing this?
First of all, your code is leaking memory like no good! Next you only copy the first element and not even that if the first element happens to be the one you want to remove. Also, when you return from your function, you haven't changed your internal state at all. You definitely want to do something along the lines of
Data** it = std::find(values, values + count, x);
if (it != values + count) {
std::copy(it + 1, values + count, it);
--count;
return true;
}
return false;
That said, if anybody taught you to implement something like std::vector<T> involving reallocations on every operation, it is time to change schools! Memory allocations are relatively expensive and you want to avoid them. That is, when implementing something like a std::vector<T> you, indeed, want to implement it like a std::vector<T>! That is you keep an internal buffer of potentially more element than there are and remember how many elements you are using. When inserting a new element, you only allocate a new array if there is no space in the current array (not doing so would easily result in quadratic complexity even when always adding elements at the end). When removing an element, you just move all the trailing objects one up and remember that there is one less object in the array.
Try this:
bool remove(Data * x)
{
bool found = false;
// See if x is in the array.
for (int i = 0; i < count; i++) {
if (x != values[i]) {
found = true;
break;
}
}
if (!found)
{
return false;
}
// Only need to create the array if the item to be removed is present
Data **newArray = new Data *[count - 1];
// Copy the content to the new array
int newIndex = 0;
for (int i = 0; i < count; i++)
{
if (x != values[i])
newArray[newIndex++] = values[i];
}
// Now change the pointers.
delete[] values;
count--;
values = newArray;
return true;
}
Note that there's an underlying assumption that if x is present in the array then it's there only once! The code will not work for multiple occurrences, that's left to you, seeing as how this is a school exercise.