Null pointers to classes - c++

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).

Related

C++ vector segmentation error when accessing the first element

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 :)

infinite loop in stack implementation c++

this is my first data structure program. I am implementing a simple stack using array with push, pop and initialize functions. I am getting an infinite loop as the output. Could you please tell me why is this so?
#include<iostream>
using namespace std;
# define SIZE 6
class stack{
public:
void init();
void push(int i);
int pop();
int top;
int stck[SIZE];//bydefault private
};
void stack::init()
{
top=0;
return;
}
void stack::push(int i)
{
if(top==SIZE)
{
cout<<"stack is full";
return;
}
else
{
top=top+1;
stck[top]= i;
return;
}
}
int stack::pop()
{
if(top==0)
{
cout<<"stack is empty. \n";
return 0;
}
else
{
top = top-1;
return(stck[top-1]);
}
}
int main()
{
stack stack1;
stack1.init();
int a;
int m;
while(a!=4)
{
cout<<"1. push 2. pop 3.display 4.exit .\n";
cin>>a;
if(a==1){
cout<< "enter value";
cin>>m;
stack1.push(m);
}
if(a==2)
{
cout<<"popped"<< stack1.pop();
}
if(a==3)
{
for(int k=0; k<=stack1.top;k++)
{
cout<<stack1.stck[k];
}
}
}
}
You never initialize a, so your program has undefined behaviour. Specifically, the while (a != 4) line performs an lvalue-to-rvalue conversion of a while its value is indeterminate, which the C++ standard explicitly states as undefined behaviour in section 4.1.
However, I doubt this is causing the issue at hand. In practice, unless the optimizer just optimized all your code out, your program should usually behave as expected; it's only when a == 4 on the first loop that you have problems. This doesn't make the code acceptable, but there's probably more to it.
I suspect the problem is that you use top to represent one past the number of elements. When you have zero elements, you point to the first; when you have one, you point to the second, etc. This means you're pointing to the first unused element.
However, in both your push and pop functions, you change top first and only then access the stack, but acting as if you didn't change it:
top = top + 1;
stck[top] = i;
When your stack is empty, this will set top to 1 and then access stck[1]. Meanwhile, stck[0] is left unset. When popping, you have the opposite:
top = top - 1;
return stck[top-1];
This sets top back to 0, but returns stck[-1], which is out of bounds.
I suspect that if you push SIZE values onto the stack, you will end up overwriting unrelated memory, which could cause all kinds of trouble. I still don't see how an infinite loop will follow, but given the behaviour is undefined, it is certainly a possible result.
(The alternative is that you at some point enter something other than a number. Seeing as you never check whether your input succeeded, if a != 4 and you enter something invalid, all further reads will fail, and a will remain unequal to 4. You could fix this by making changing your while to be
while (a != 4 && std::cin)
In that case, if you enter something invalid and std::cin goes into a non-good state, your loop (and thus program) will end.)
You only have a single loop, terminated based on user input.
If cin>>a fails, a will have whatever value it started with (undefined in your code), and you will loop on that unchanging value.
Typical ways for the input call to fail include
pressing control+D (on a *nix system)
pressing control+Z (on a Windows system)
redirected input from a pipe or file which is exhausted
There may be other causes of failed input as well.

C++ Function will not execute more than once

I've tried looking around but I can't find anything about this anywhere.
I'm writing a custom array class with a "push" function to add a value to the array.
It seems to work perfectly fine but won't execute more than once.
Take the main method below for example:
int main()
{
Array<int> test(4,5);
test.push(4);
test.writeOrdered("Output.txt");
return 0;
}
This will put the int value 4 into the array at the first available position and execute the writeOrdered function.
The following main method, on the other hand:
int main()
{
Array<int> test(4,5);
test.push(4);
test.push(5);
test.writeOrdered("Output.txt");
return 0;
}
This will put the number 4 into the array at the first available point as above and then stop. It won't execute any further lines of code.
Here's the push function for reference:
void push(Datatype p_item)
{
bool inserted = false;
int i = 0;
while (inserted == false)
{
if (m_array[i] < 0)
{
m_array[i] = p_item;
i++;
inserted = true;
cout << p_item << " saved to array" << endl;
system("pause");
}
}
}
You have an infinite loop. After the first insert m_array[0] >= 0 and i never grows. You would have found it out, had you debugged the code somehow.
Basically I don't understand your push function but the way it is, after you insert a non-negative value into the first position any further call to your push function results in a tight loop.
I imagine that you want the i++ outside the if statement.
Without seeing the full implementation of the Array class I would guess that the array m_array contains negative numbers by default. This will allow the first call to the push method to succeed. The next call to the method contains a value of 4 at index 0 and will be stuck in an infinite loop because inserted will never be set to true nor will the value of i be incremented.

Array setup in constructor means failure later on

I had an issue where my code segfaulted on attempting to use the size() function of a list. On the advice of stackoverflow :-) I constructed a minimum case in which the segfault occurs (on the call inventory.size() below). It is:
#include <list>
class Thing {};
class Player {
private:
int xpCalcArray[99];
std::list<Thing*> inventory;
public:
Player();
int addToInv(Thing& t); // return 1 on success, 0 on failure
};
Player::Player() {
// set up XP calculation array
for (int i=1; i<100; i++) {
if (i<=10) {
xpCalcArray[i] = i*100;
}
if (i>10 && i<=50) {
xpCalcArray[i] = i*1000;
}
if (i>50 && i<=99) {
xpCalcArray[i] = i*5000;
}
}
}
int Player::addToInv(Thing& t) {
if (inventory.size() == 52) {
return 0;
} else {
inventory.push_back(&t);
}
return 1;
}
int main(int argc, char *argv[]) {
Thing t;
Player pc;
pc.addToInv(t);
return 1;
}
I notice that when I remove the setting up of the array in the Player cosntructor, it works fine, so this looks to be the problem. What am I doing wrong?
You are accessing your array out of bounds, which results in undefined behaviour. The valid index range for this array
int xpCalcArray[99];
is 0 to 98. You are accessing index 99 here:
if (i>50 && i<=99) {
xpCalcArray[i] = i*5000;
}
Your outer loop should be
for (int i=0; i<99; i++) { ... }
Note I start from 0, although it is an assumption that you actually want to access the first element.
Then your final condition can be simplified to
if (i>50) {
xpCalcArray[i] = i*5000;
}
If you intended to use a size 100 array, then you need
int xpCalcArray[100];
then loop between int i=0; i<100;.
You are accessing outside the bounds of your array. Doing so causes undefined behaviour and so there is no logical explanation for anything that occurs afterwards. The size of your array is 99 and so the last index is 98. Your for loop goes up to 99, however.
Either make your array size 100:
int xpCalcArray[100];
Or change your for condition to i < 99.
You are overwriting your array of 99 ints by attempting to modify the 2nd→100th elements (rather than 1st→99th).
In your case, this happens to overwrite some memory within the std::list<Thing*> (which exists in memory directly after the array — not always, but evidently for you today) and thus, when you try to use the list, all hell breaks loose when its internal member data is no longer what it thought it was.
You xpCalcArray is defined from 0 up to 98 (being 99 elements large).
Your loop goes from 0 up to 99, taking 100 steps.
The last loop cycle, writes xpCalcArray at location 99, which does not exist. This (indirectly) results in your segmentation fault as shown by the answer of Lightness Races in Orbit.
So, increase the size of xpCalcArray by 1:
int xpCalcArray[100];

Vector push_back in while and for loops returns SIGABRT signal (signal 6) (C++)

I'm making a C++ game which requires me to initialize 36 numbers into a vector. You can't initialize a vector with an initializer list, so I've created a while loop to initialize it faster. I want to make it push back 4 of each number from 2 to 10, so I'm using an int named fourth to check if the number of the loop is a multiple of 4. If it is, it changes the number pushed back to the next number up. When I run it, though, I get SIGABRT. It must be a problem with fourth, though, because when I took it out, it didn't give the signal.
Here's the program:
for (int i; i < 36;) {
int fourth = 0;
fourth++;
fourth%=4;
vec.push_back(i);
if (fourth == 0) {
i++;
}
}
Please help!
You do not initialize i. Use for (int i = 0; i<36;). Also, a new variable forth is allocated on each iteration of the loop body. Thus the test fourth==0 will always yield false.
I want to make it push back 4 of each number from 2 to 10
I would use the most straight forward approach:
for (int value = 2; value <= 10; ++value)
{
for (int count = 0; count < 4; ++count)
{
vec.push_back(value);
}
}
The only optimization I would do is making sure that the capacity of the vector is sufficient before entering the loop. I would leave other optimizations to the compiler. My guess is, what you gain by omitting the inner loop, you lose by frequent modulo division.
You did not initialize i, and you are resetting fourth in every iteration. Also, with your for loop condition, I do not think it will do what you want.
I think this should work:
int fourth = 0;
for (int i = 2; i<=10;) {
fourth++;
fourth%=4;
vec.push_back(i);
if (fourth==0) {
i++;
}
}
I've been able to create a static array declaration and pass that array into the vector at initialization without issue. Pretty clean too:
const int initialValues[36] = {0,1,2...,35};
std::vector foo(initialValues);
Works with constants, but haven't tried it with non const arrays.