C++ class and empty arrays - c++

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];
}

Related

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

c++ Dynamic 2d array not using default constructor

I got a problem that is beyond my knowledge. I'm working on a HGE project, but this is a c++ issue, not the HGE engine itself.
The question:
I want to create a 2D array with 3 different animations on 5 different turtles. However, I need to use a constructor in HGE something like this;
turtleAnim[i] = new hgeAnimation( turtleTexture, 6, 6, 0, 0, 110, 78 )
But I don't know how to do it! All examples on the interwebz handle the problem as if it got a default constructor. Something like this:
in class:
#define TURTLECOUNT 5
#define TURTLEANIMATIONS 3
private:
hgeAnimation** turtleAnim;
in the.cpp
turtleAnim= new hgeAnimation*[TURTLECOUNT];
for(int i=0; i<TURTLECOUNT; i++)
{
turtleAnim[i]= new hgeAnimation[TURTLEANIMATIONS]; // Uses default constructor. I don't want that cuz it doesn't exists.
turtleAnim[i]->Play();
}
First, you have to decide whether you want your objects on the stack or the heap. Since they're objects, you probably want them on the heap, which means your 2D array will have 3 stars, and you will access the animations like this:
hgAnimation* theSecondAnimOnTheFourthTurtle = turtleAnim[4][2];
theSecondAnimOnTheFourthTurtle->DoSomething();
If that's what you want, then first you make the matrix of pointers.
hgeAnimation*** turtleAnim = new hgeAnimation**[TURTLECOUNT];
Then you can loop through the turtles. For each turtle, you make an array of pointers to the animations. For each element of that array, you make the animation itself.
for (int turt=0; turt<TURTLECOUNT; ++turt) {
turtleAnim[turt] = new hgeAnimation*[TURTLEANIMATIONS];
for (int ani=0; ani<TURTLEANIMATIONS; ++ani) {
turtleAnim[turt][ani] = new hgeAnimation(parameter1, par2, par3);
}
}
If that looks tricky, deleting all the arrays will be a pain too:
for (int turt=0; turt<TURTLECOUNT; ++turt) {
for (int ani=0; ani<TURTLEANIMATIONS; ++ani) {
delete turtleAnim[turt][ani];
}
delete[] turtleAnim[turt];
}
delete[] turtleAnim;
The fact that this is tricky is a good sign that there's probably a more simple way to design it.
How about a turtle class that has a member like:
class ATurtle {
private:
std::vector<hgeAnimation*> myAnimations;
Then in your class's constructor, you can do whatever you want in order to make the animations.
ATurtle::ATurtle(par1, par2, par3) {
myAnimations.push_back( new hgeAnimation(par1, x, y) );
myAnimations.push_back( new hgeAnimation(par2, z, a) );
myAnimations.push_back( new hgeAnimation(par3, b, c) );
}
That way, you can make your turtles in a single array:
ATurtle* turtles[TURTLECOUNT];
for (int t=0; t<TURTLECOUNT; ++t) {
turtles[t] = new ATurtle(par1, par2);
}
And in your turtle class, you would access the animations like so:
(*(myAnimations.at(1)))->DoSomething();
or
std::vector<hgAnimation*>::iterator i, end=myAnimations.end();
for (i=myAnimations.begin(); i!=end; ++i) {
(*i)->DoSomething();
}
You will still have to call delete on each element of your vector in this case, though, since you called new for every element.
ATurtle::~ATurtle() {
std::vector<hgAnimation*>::iterator i, end=myAnimations.end();
for (i=myAnimations.begin(); i!=end; ++i) {
delete (*i);
}
}

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

weird issue in an SDL-based Hanoi Tower Game

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.

Access Violation reading elements of an array

I've written my own code to parse an .obj model file - essentially just ASCII text. The file gets parsed and stored in the class correctly according to my tests. I can read back the values (from data members) just fine in the loading function.
The problem occurs when I try to read back the values in my main rendering loop. There is an access violation error on the line beginning "int v":
for(int i = 0; i<data.numFaces; i++){
for(int j = 0; j<3; j++){ //Assuming triangles for now.
int v = data.faceList[i].vertex[j]; // Access violation here.
double vX = data.vertexList[v].x;
double vY = data.vertexList[v].y;
double vZ = data.vertexList[v].z;
glVertex3d(vX, vY, vZ);
}
}
I'm not exactly sure why this happens, and I've checked everything I could possibly think of. I'm not very experienced in C++. Most of my programming experience is in Java, Python and PHP although I have previously written a medium sized project in C++.
I'm sure the problem is something basic related to memory allocation or pointers used for the dynamic arrays.
Here are the relevant parts of code in the obj loading class:
ObjData ObjLoader::LoadObj(std::string filename){
//... Initalization ...
// 1st pass: find number of elements so array sizes can be defined.
while(!file.eof()){
//...
}
//...close file...
_data.faceList = new ObjFace[_data.numFaces];
_data.vertexList = new ObjVert[_data.numVertices];
_data.uvList = new ObjUV[_data.numUVcoords];
_data.normalList = new ObjNormal[_data.numNormals];
//TODO: Make size dynamic according to each face. Just use the first 3 points for now.
for (int i = 0; i < _data.numFaces; i++){
_data.faceList[i].vertex = new int[3];
_data.faceList[i].normal = new int[3];
_data.faceList[i].uv = new int[3];
}
//... file stuff ...
// 2nd pass: read values into arrays.
while(!file.eof()){
//...
if(type=="v"){
_data.vertexList[currentVertex].x = atof(param1.c_str());
_data.vertexList[currentVertex].y = atof(param2.c_str());
_data.vertexList[currentVertex].z = atof(param3.c_str());
currentVertex++;
}else if(type=="vt"){
_data.uvList[currentUV].u = atof(param1.c_str());
_data.uvList[currentUV].v = atof(param2.c_str());
currentUV++;
}else if(type=="vn"){
_data.normalList[currentNormal].x = atof(param1.c_str());
_data.normalList[currentNormal].y = atof(param2.c_str());
_data.normalList[currentNormal].z = atof(param3.c_str());
currentNormal++;
}else if(type=="f"){
//...Within loop over each vertex in a single face ...
if(endPos != string::npos){
// Value before 1st "/" (Vertex index).
// ...find value in string...
_data.faceList[currentFace].vertex[i] = atoi(token.c_str()) -1; // File format begins indices from 1.
// Value between slashes (UV index).
// ...find value in string...
_data.faceList[currentFace].uv[i] = atoi(token.c_str()) -1;
// Value after 2nd "/" (Normal index).
// ...find value in string...
_data.faceList[currentFace].normal[i] = atoi(token.c_str()) -1;
}
//...End of loop over every vertex in a single face...
currentFace++;
}
}
return _data;
}
And the structs ObjFace, ObjVert, ObjUV and ObjNormal are defined as:
struct ObjVert{
float x, y, z;
};
struct ObjUV{
float u, v;
};
struct ObjNormal{
float x, y, z;
};
// Contains indexes.
struct ObjFace{
int* vertex;
int* uv;
int* normal;
};
Thanks for any help. Also, any good sources on avoiding these types of errors in future would be appreciated.
I had typed up some silly response which I realized wasn't right...but I had to keep thinking on it, and I came up with another idea.
Where is this object being assigned?
Your code isn't clear if data and _data are the same object or not, but I noticed that your method there seems to return _data as an object. I'm led to believe that perhaps you are using an assignment like ObjData data = LoadObj("myfilename"); somewhere?
If this is the case, I believe your problem may come from a lack of a copy constructor or overloaded assignment operator for your ObjData class. (I'm not a C++ guru, so I don't recall exactly which one this would fall under. Hopefully someone else can confirm if we're on the right track).
If your pointers are not being copied correctly during the copy and assignment (returning from LoadObj calls a copy constructor iirc, and then the obvious assignment to data), then even though you intended to already have an array of int at that location, you may in fact be accessing uninitialized memory, thus causing your Access Violation.
I'm not an expert with either copy constructors or overloaded assignment operators, but a quick way around this would be to return a pointer to an ObjData rather than to return an object itself.
At first glance I didn't see anything blatantly wrong. But if as you say it is exploding at int v = data.faceList[i].vertex[j]; then it seems very likely that the problem is either i or j or both are too big or too small.
Aside from the obvious approach of getting cozy with your debugger and flattening this bug out, the best approach to solving problems like these is probably to avoid them altogether. Certain things programmers do are more prone to errors than others. The list is long, but you do at least two of them, in spades, in your code.
1) You use dynamically-allocated arrays
2) You use hand-crafted loops
Try to avoid doing these things by using the tools that C++ gives you. Start with #1, and get rid of the dynamically-allocated arrays.
You have a struct:
struct ObjFace{
int* vertex;
int* uv;
int* normal;
};
...with 3 pointers-to-arrays-of-int. Instead of doing that, use a vector:
struct ObjFace{
vector<int> vertex;
vector<int> uv;
vector<int> normal;
};
...and then a whole lot of code you had to write before becomes much simpler now, and much less prone to mistakes:
// all this goes away
//_data.faceList = new ObjFace[_data.numFaces];
//_data.vertexList = new ObjVert[_data.numVertices];
//_data.uvList = new ObjUV[_data.numUVcoords];
//_data.normalList = new ObjNormal[_data.numNormals];
...and:
// now you ask the vector how many elements it really has
for(int i = 0; i<data.faceList.size(); i++){
for(int j = 0; j<data.faceList.size(); j++){ //Ask the vector instead of assuming triangles
int v = data.faceList[i].vertex[j]; // Access violation here.
double vX = data.vertexList[v].x;
double vY = data.vertexList[v].y;
double vZ = data.vertexList[v].z;
glVertex3d(vX, vY, vZ);
}
}
Now, look at that loop. Loops are a very common source of errors. The best loop is the loop you never have to write. So use the STL's algorithms instead. Add a function to ObjFace to execute glVertex3d on each of it's elements:
struct ObjFace{
//...
void do_vertex() const
{
typedef vector<int> ints;
for( ints::iterator it = vertex.begin(); it != vertex.end(); ++it )
glVertex3d(it->x, it->y, it->z);
}
};
...then go back and whittle down that original loop:
(psudocode, actual syntax is more complex)
typedef vector<ObjFace> ObjFaces;
for( ObjFaces::iterator it = data.faceList.begin(); it != data.faceList.end(); ++it )
it->do_vertex();
...or, with a little more effort:
for_each( data.faceList.begin(), data.faceList.end(), &ObjFace::do_vertex );