weird issue in an SDL-based Hanoi Tower Game - c++

I want to create a SDL-based Hanoi Tower Game, but before I proceed to writing "engine", I wanted to test my Hanoi in a console. Surprisingly, it turned out to be quite buggy.
CTower tower[3];
tower[0] = CTower(3);
tower[1] = CTower(3);
tower[2] = CTower(3);
init(&tower[0]); //prepare first tower
tower[0].Print();
This piece of code should create 3 arrays (of size 3) and fill 'em with 0 (zeros). Then, in init(), I prepare the first tower (fill it with vaild discs). However simple may it seem, my application halts on printing and doesn't fill the remaining arrays (with 0). What's strange, function init() works just fine.
I would appreciate any help.
Here's some code to check:
class CTower {
uint16 *floors, floorsNum;
void Init();
public:
(...) //definitions, probably of zero importance
};
void CTower::Init() {
//private member, filling with zeros
for (uint16 i = 0; i < floorsNum; i++)
floors[i] = 0;
}
CTower::CTower() {
//default initialiazer
floors = NULL;
floorsNum = 0;
}
CTower::CTower(uint16 nfloors) {
floors = new uint16[nfloors];
floorsNum = nfloors;
this->Init();
}
CTower::~CTower() {
delete[] floors;
floorsNum = 0;
}
void CTower::Print() {
if (floorsNum == 0) printf("EMPTY TOWER!");
else
for (uint16 i = 0; i < floorsNum; i++)
printf("%d\n", floors[i]);
}
void init(CTower *tower) {
//a friend method of CTower
for (uint16 i = 0; i < tower->floorsNum; i++)
tower->floors[i] = i+1;
}
My application source: https://rapidshare.com/files/2229751163/hanoi-tower.7z

Problem is with your initialisation and allocation of your class. It seems you have forgotten that Resource Acquisition is Initialisation.
You are facing a free corruption : you call delete[] on a not allocated attribute.
You have this constructor :
CTower::CTower() {
//default initialiazer
floors = NULL;
floorsNum = 0;
}
Which does NOT allocates memory but which is destroyed with :
CTower::~CTower() {
delete[] floors;
floorsNum = 0;
}
A simple way to fix your program is to allocate directly with the working constructor :
int main(void) {
CTower tower[3] = { CTower(3), CTower(3), CTower(3) };
init(&tower[0]);
tower[0].Print();
printf("\n");
tower[1].Print();
return 0;
}
But it would be far better to also fix your Class, either in Destructor or in Constructor part.

Unless you have been specifically asked not to use a std::vector then I would consider changing your code to use one as it makes life a lot simpler.
With regards to your specific code example. You are going to have problems due to the lack of a copy constructor and assignment operator as the defaults generated by the compiler are not going to be suitable for your class.
I would also consider getting rid of the friend function void init(CTower *tower) as this really isn't good practice.
I would provide a code example but this question is tagged as "Homework" so I will let you do the research yourself.

Related

Exception thrown at 0x0037A5C2 project.exe: 0xC0000005: Access violation writing location 0xDDDDDDDD at the end of the program

I have encountered this runtime exception at the very end of the program by simply creating an instance of the specified class, so I presume the issue lies with either the constructor, copy constructor, copy assignment operator or destructor. I have read up on and followed the rule of three to the extent of my limited cpp knowledge.
Source.cpp
#include "Header.h"
#include <iostream>
using namespace std;
int main() {
string command = "CREATE TABLE table_name IF NOT EXISTS ((column_1_name,type,default_value), (column_2_name,type,default_value))";
string columns[20] = { "column_1_name,type,default_value", "column_1_name,type,default_value" };
string commandData[9] = { "table_name", "IF NOT EXISTS" };
CommCREATETABLE comm(command, columns, commandData, 2, 2);
}
Relevant code from Header.h
class CommCREATETABLE {
string fullCommand = "";
string* columns = nullptr;
string* commandData = nullptr;
string tableName = "";
int nrOfColumns = 0;
int nrOfElements = 0;
bool valid = false;
Constructor:
CommCREATETABLE(string command, string* columns, string* commandData, int nrOfRows, int nrOfElements) {
this->setNrOfColumns(nrOfRows);
this->setNrOfElements(nrOfElements);
this->setCommand(command);
this->setColumns(columns);
this->setCommandData(commandData);
this->valid = checkInput(this->commandData, this->columns);
this->setTableName(commandData[0]);
}
Copy constructor, copy assignment operator, destructor:
CommCREATETABLE(const CommCREATETABLE& comm) {
this->setNrOfColumns(comm.nrOfColumns);
this->setNrOfElements(comm.nrOfElements);
this->setCommand(comm.fullCommand);
this->setColumns(comm.columns);
this->setCommandData(comm.commandData);
this->setTableName(comm.tableName);
this->valid = comm.valid;
}
~CommCREATETABLE() {
if (this->columns != nullptr) {
delete[] this->columns;
}
if (this->commandData != nullptr) {
delete[] this->commandData;
}
}
CommCREATETABLE& operator=(const CommCREATETABLE& comm) {
this->setCommand(comm.fullCommand);
this->setColumns(comm.columns);
this->setCommandData(comm.commandData);
this->setTableName(comm.tableName);
this->setNrOfColumns(comm.nrOfColumns);
this->setNrOfElements(comm.nrOfElements);
this->valid = checkInput(this->commandData, this->columns);
return *this;
}
The only setters that deal with dynamic memory allocation are the following:
void setColumns(const string* columns) {
if (this->nrOfColumns >= 0) {
this->columns = new string[this->nrOfColumns];
memcpy(this->columns, columns, this->nrOfColumns * sizeof(string));
}
else throw EmptyCommandException();
}
void setCommandData(const string* commandData) {
if (this->nrOfElements >= 0) {
this->commandData = new string[this->nrOfElements];
memcpy(this->commandData, commandData, this->nrOfElements * sizeof(string));
}
else throw EmptyCommandException();
}
At a quick glance I would say the issue is in your setColumns and setCommandData functions. (I might of course be wrong, I did not try to run the code you presented nor the changes I made -- so there might also be a typo somewhere.)
There you use memcpy to copy the strings into your class. However, internally a C++ string holds a pointer to the actual string, so using memcpy actually only copies that pointer. As a result, once the original string gets deleted, the pointer you copied into your class is no longer valid (as the memory has already been freed). As a result, once your class also gets deleted it attempts to delete memory that has already been freed. That is probably where your error comes from.
In fact, if you added lines to your program where you tried to manipulate your class (after the original input strings have already been deleted), the problem would present itself even sooner, as you would be accessing memory that has already been freed. This would lead to undefined behaviour, which typically ends with a crash at some point.
A quick fix would be to change the way you copy the data, by using = for each string (in that way copying the actual strings into a new location in memory, rather than copying the pointer).
void setColumns(const string* columns) {
if (this->nrOfColumns > 0) { // Creating an array of size 0 is also not a good idea.
this->columns = new string[this->nrOfColumns];
for (int i = 0; i < nrOfColumns; i++) { // You don't need this everywhere.
this->columns[i] = columns[i];
// I don't think naming things the exact same way is good practice.
}
}
else throw EmptyCommandException();
}
void setCommandData(const string* commandData) {
if (this->nrOfElements > 0) { // Creating an array of size 0 is also not a good idea.
this->commandData = new string[this->nrOfElements];
for (int i = 0; i < nrOfElements; i++) { // You don't need this everywhere.
this->commandData[i] = commandData[i];
// I don't think naming things the exact same way is good practice.
}
}
else throw EmptyCommandException();
}
Alternatively, if you want to avoid making copies you should look into move, but I would suggest against this for the time being, if you are still learning. You'll get there soon enough.

C++ class and empty arrays

Hello I try to implement a little machine learning for Arduino. It should run on a x86 also to make it easier to debug and train it.
Unfortunately there is some problem (with memory I guess).
If I try to use something like eg. weights[1][1] I get segmentation faults. Valgrind or gdb show the memory is null.
My guess is that layers = new Layer[5]; causes this empty memory and layers[1] = Layer(preLayer, 10, afunc); does not set the memory as I would expect it.
I found some hints to implement something like Layer& Layer::operator=(const Layer& other) // copy assignment but I don't understand why. I even tried to fix it this way but this lead to new problems.
Question:
Is there a way to avoid "empty" Layers? I would like to avoid Layer(); and layers = new Layer[5]; at all if sensible.
//afunc is a function
layers = new Layer[5];
Layer *preLayer = &layers[0];
layers[1] = Layer(preLayer, 10, afunc);
Layer.h
class Layer
{
public:
Layer *preLayer;
float **weights;
int weightSize;
float *biases;
float *neurons;
int neuronsSize;
void (*afunc)(float *);
Layer();
Layer(Layer *input, int outputs, void (*afunc)(float *));
~Layer();
void calculateNeurons();
private:
Layer(const Layer &layertoCopy); // not implemented
};
Layer.c
Layer::Layer() {}
Layer::Layer(Layer *preLayer, int neuronsSize, void (*afunc)(float *)): preLayer(preLayer), neuronsSize(neuronsSize), afunc(afunc)
{
neurons = new float[this->neuronsSize]();
if(this->preLayer) {
weightSize = (*this->preLayer).neuronsSize;
weights = new float*[this->neuronsSize];
for(int i = 0; i < this->neuronsSize; ++i) {
weights[i] = new float[weightSize];
}
biases = new float[this->neuronsSize]();
}
}
Layer::~Layer()
{
}
With your sample code,
layers[1] = Layer(preLayer, 10, afunc);
you have two problems. In the non-default constructor, you check
if(this->preLayer)
You have sent in something which is not null, but doesn't initialise anything.
&layers[1] = new Layer(0, 10, afunc);
should avoid this.
However, if you make a std::vector instead of the c-style array you can push_back new layers, without having to use the pointer.
Also, if you want to use pointers, make the destructor delete them appropriately.
Your layers were made with default constructor first when you wrote "layers = new Layer[5]". Maybe try with:
Layer** layers = new Layer*[5];
Layer* prevLayer = nullprt;
for(int i=0;i<5;i++){
layers[i]=new Layer(prevLayer,10,afunc);
prevLayer=layers[i];
}

I am stuck with copying a class given an address, I am segfaulting

I have struggled with it for a while but I really can't get it, I am just getting segfaults. I am trying to copy a class, the function I am writing to copy is also below. Crossed out are combinations that I have tried in vain, it's time to call for help
class Scene
{ private:
int max;
int* x_row, *y_col; // maximum and min coordinates of each image
Image**image_layers;
}
void Scene::_copy(const Scene &source)
{
max = source.max;
x_row = new int[source.x_row];
y_col = new int[source.y_col];
image_layers = new Image*[source.max];
for(int i = 0; i < source.max; i++)
{
if(source.image_layers[i] != NULL)
{
//image_layers[i] = new Image(*(source.image_layers[i]));
// image_layers[i] = new Image;
//*image_layers[i] = *source.image_layers[i];
// image_layers[i] = source.image_layers[i];
}
else
{
image_layers[i] = NULL;
}
x_row[i] = source.x_row[i];
y_col[i] = source.y_col[i];
}
EDIT:
I forgot to say that this function is called as " scene(*set) "
The segfault happens here or because of this:
x_row = new int[source.x_row];
y_col = new int[source.y_col];
On the right hand side, you use the address source.x_row as an array size. This is a very large number that most likely will cause the allocation to fail.
You need to keep a member for holding the size or better yet use a std::vector<int> object instead.
Copying C arrays are done faster with memcpy. With C++ vectors, you can just assign one to the other:
x_row = source.x_row
Nothing to do with the question, but this function should be named operator=, will make using the class easier by assigning one instance to another:
Scene & Scene::operator=(const Scene &source)
{
// copy elements
...
return *this;
}
x_row = new int[source.x_row];
y_col = new int[source.y_col];
Are you sure about above code?
source.x_row is pointer

Array "breaks" when resizing

Well, I have a class which is supposed to be a container for quadratic polynomials (which is a template and I'm using floats there, but that shouldn't matter much). I made it using a dynamic array, and I was supposed to overload + and - operators... Not a problem, eh? Well, it seemed all nice and dandy until I actually run it.
listf listf::operator+(listf rhs)
{
listf newlist;
for(int i = 0; i < elementcount; ++i)
newlist.add(array[i]);
for(int j = 0; j < rhs.elementcount; ++j)
newlist.add(rhs.array[j]);
std::cout<<newlist;
return newlist;
}
Nothing much. Should do its job correctly, right? That cout is just to check if it works. But it does not.
Should do something like this, right?
With one list consisting of:
X^2+5x+52.4
2X^2+7x-12
and the second one having just X^2+2X+1, it should make a list and display:
X^2+5x+52.4
2X^2+7x-12
X^2+2X+1
Buuuut no, it comes to this:
-1.5584e+038X^2-1.5584e+038x-1.5584e+038
-1.5584e+038X^2-1.5584e+038x-1.5584e+038
-1.5584e+038X^2-1.5584e+038x-1.5584e+038
I've been battling with it for quite some time and have not found why it would do that.
Code for adding new polynomials is still quite simple:
void listf::add(polynomial<float> plnm)
{
if(array == NULL)
{
++elementcount;
array = new polynomial<float>[elementcount];
array[0] = plnm;
}
else
{
array = resize(array, elementcount+1, elementcount);
array[elementcount++] = plnm;
}
}
And resize is a private function in this class:
polynomial<float>* listf::resize(polynomial<float>* arr, int newSize, int oldSize)
{
polynomial<float>* newArr = new polynomial<float>[newSize];
for(int i = 0; i < oldSize; ++i)
{
newArr[i] = arr[i];
}
delete[] arr;
return newArr;
}
If we're making a smaller array (for deleting objects), I just put oldSize equal to newSize (I know it's a bad practice and confusing for others, but I was just testing things :( )
I'm out of ideas. Adding new elements to an object seems working, but when I want to add two objects it breaks, prints elements that are not correct and then crashes with CodeLite reporting something like "ntdll!LdrVerifyImageMatchesChecksumEx" in Call Stack. Even better, when I tested it right now, it displayed correct values, but still crashed at return.
Forget the home-made dynamic array and use vector. Whenever you go into the realm of classes and memory management, it isn't as trivial as coding up a few new[] and delete[] calls. It can stop you dead in your tracks in the development of your program.
#include <vector>
//...
typedef std::vector<polynomial<float> > PolynomialFloatArray;
//...
class listf
{
PolynomialFloatArray array;
//...
void add(const polynomial<float>& plnm);
//...
PolynomialFloatArray& resize(PolynomialFloatArray& arr, int newSize)
};
//...
void listf::add(const polynomial<float>& plnm)
{
array.push_back(plnm);
}
PolynomialFloatArray& listf::resize(PolynomialFloatArray& arr, int newSize)
{
arr.resize(newSize);
return arr;
}
There in a nutshell is all of that code you wrote, reduced down to 2 or 3 lines.
Like the comments on the question point out, you would probably be better off using std::vector for this, as it has push_back() to add stuff to the end, and automatically resizes itself to do so, though you can force it to resize with resize().

Deleting double pointer causes heap corruption

I am using a double pointer but when I try to delete it it causes Heap Corruption: CRT detected that the application wrote to memory after end of heap. It "crashes" inside the destructor of the object:
Map::~Map()
{
for(int i = 0; i < mTilesLength; i++)
delete mTiles[i];
delete[] mTiles;
}
mTiles is declared something like this:
Tile **mTiles = NULL;
mTiles = new Tile *[mTilesLength];
for(int i = 0; i < mTilesLength; i++)
mTiles[i] = new Tile(...);
If notable mTiles is a object of "Tile" which inherits from a object "Sprite" all 3 destructors are set as virtual (map, tile, sprite), not sure if that makes any difference but seemed to work until now.
The code you posted does not seem to have any problems in it. I created a simple, self contained, compiling (and correct) example from it:
struct Tile {int x; Tile():x(7) {}};
struct Map {
Tile **mTiles;
int mTilesLength;
Map(int TilesLength_);
~Map();
};
Map::~Map()
{
for(int i = 0; i < mTilesLength; i++) {
delete mTiles[i];
}
delete[] mTiles;
}
Map::Map(int TilesLength_):
mTiles(),
mTilesLength(TilesLength_)
{
mTiles = new Tile *[mTilesLength];
for(int i = 0; i < mTilesLength; i++) {
mTiles[i] = new Tile();
}
}
int main() {
Map* m = new Map(1000);
delete m;
}
I compiled and ran it <- link, and nothing bad was noticed.
Your problem lies in code you have not shared with us. In order to find the code that is causing the problem and ask the right question, go here: http://sscce.org/
Then take your code and start trimming parts off it until the code is simple, yet still demonstrates your heap corruption. Keep copies of each version as you trim away irrelevant code so you don't skip over the part where the problem occurs (this is one of the many reasons you want a version control system even on your personal projects).