C++ pointers and arrays - c++

I have a problem with dynamic array.
In header file class i have this:
class CTerrain
{
...
CRock *rocks;
int numRocks;//=0
...
}
and in cpp i have this:
void CTerrain::Create()
{
numRocks = 0;
int NUM_ROCKS = rand()%10+1;
for(int i=0;i<NUM_ROCKS;i++)
{
rocks = new CRock;
numRocks++;
...
}
}
void CTerrain::Render()
{
for(int i=0;i<numRocks;i++)
rocks[i].render();//it works ok when here is 0 instead of 'i'
}
When I run this code I got error:
Unhandled exception at 0x00913aea in OpenGL.exe: 0xC0000005: Access violation reading location 0x1c00001f.
Thanks for any help, I have been trying to resolve this problem for like 4 hours...
EDIT:
Ok, so I changed Create() method to this:
void CTerrain::Create()
{
numRocks = 0;
int NUM_ROCKS = rand()%10+1;
rocks = new CRock[NUM_ROCKS];
for(int i=0;i<NUM_ROCKS;i++)
{
rocks[i].position = ...
numRocks++;
...
}
and also added delete [] rocks and now it's working.

Your Create function would be more like
void CTerrain::Create()
{
int NUM_ROCKS = rand()%10+1;
rocks = new CRock[NUM_ROCKS];
numRocks = NUM_ROCKS;
for(int i=0; i<NUM_ROCKS; i++)
{
rocks[i] = CRock{};
}
}

Just to add bit of explanation to above answer. Here:
for(int i=0;i<NUM_ROCKS;i++)
{
rocks = new CRock;
numRocks++;
...
}
What you do is, each time assign new instance of CRock to the pointer rock; thereby losing reference to the old object and creating memory leaks. Use a solution similar suggester by Cyber.

First off, rocks is pointer to CRocks. Your implemenation:
rocks[i].render() should be something like this:
rocks = new CRock [x]; (where x is the number of objects of type CRock.)
rocks[i] -> render().
delete rocks[i] // Just be sure to delete.
You may want to reference this for your solution on handling how a dynamic array of objects.
This other reference is good.

rocks = new CRock;
you overwrite CRock* pointer rocks in this line over and over again
Use this
rocks = new CRock[NUM_ROCKS];

Related

Memory Error using lambda function with array

const int bookBoatNum = 10;
Wt::WPushButton *buttonBookBoat[bookBoatNum];
Wt::WDialog *dialogBookBoat[bookBoatNum];
for (int i = 1; i < bookBoatNum; i++){
dialogBookBoat[i] = new Wt::WDialog("Book Boat");
buttonBookBoat[i] = new Wt::WPushButton();
buttonBookBoat[i]->clicked().connect(std::bind([&dialogBookBoat,i]() {
dialogBookBoat[i]->show();
}));
}
The program compiles and runs. When I click on a WPushButton object, it crashes because of the third last line because of a memory error. This code works perfectly if buttonBookBoat and dialogBookBoat are single objects, rather than an array of objects. show() is a method that displays the dialog object.
Any help is appreciated, this error has been driving me crazy and my life is on the line with this code (not really).
const int bookBoatNum = 10;
Wt::WPushButton *buttonBookBoat[bookBoatNum];
Wt::WDialog *dialogBookBoat[bookBoatNum];
for (int i = 1; i < bookBoatNum; i++){
dialogBookBoat[i] = new Wt::WDialog("Book Boat");
Wt::WDialog * tempDialog=new Wt::WPushButton();
buttonBookBoat[i] = tempDialog;
buttonBookBoat[i]->clicked().connect(std::bind([tempDialog]() {
tempDialog->show();
}));
}
I think dialogBookBoat is an array so it will not exist after the function call.

Using enums and a for-loop to create instances of a class

enum { WOOD, BRICK, GRAIN, HEMP, WOOL, RAWMETAL, HONEY, SALT, METALGOODS, MEAD, CLOTH, BEER, STOCKFISH, CLOTHING, CHEESE, PITCH, PELTS, MEAT, WINE, SPICES, TOTALRESOURCES };
// An array of strings for each of the resource names
// As long as these are in the same order as the enum everything should match up
// .: resName[PIGIRON] is "Pig Iron"
string resName[]{ "Wood", "Brick", "Grain", "Hemp", "Wool", "Raw Metal", "Honey", "Salt", "Metal Goods", "Mead", "Cloth", "Beer", "Stockfish", "Clothing", "Cheese", "Pitch", "Pelts", "Meat", "Wine", "Spices" };
enum { Edinburgh, Scarborough, Boston, London, Bruges, Haarlem, Nimwegen, Groningen, Cologne, Minden, Bremen, Erfurt, Hamburg, Lubeck, Rostock, Berlin, Ripen, Flensburg, Aalborg, Naevsted, Bergen, Stavanger, Oslo, Stockholm, Gothenburg, Malmo, Ahus, Visby, Stettin, Posen, Breslau, Danzig, Thorn, Warsaw, Konigsberg, Kaunas, Riga, Reval, Helsinki, Novgorod, TOTALTOWNS};
string townName[]{ "Edinburgh", "Scarborough", "Boston", "London", "Bruges", "Haarlem", "Nimwegen", "Groningen", "Cologne", "Minden", "Bremen", "Erfurt", "Hamburg", "Lubeck", "Rostock", "Berlin", "Ripen", "Flensburg", "Aalborg", "Naevsted", "Bergen", "Stavanger", "Oslo", "Stockholm", "Gothenburg", "Malmo", "Ahus", "Visby", "Stettin", "Posen", "Breslau", "Danzig", "Thorn", "Warsaw", "Konigsberg", "Kaunas", "Riga", "Reval", "Helsinki", "Novgorod"};
class resource
{
public:
float demand, production, businessNeeds, businessProduction;
// This function, called a constructor, is run every time a new resource is created
// In this case, it assigns 0 to everything
resource()
{
demand = 0;
production = 0;
businessNeeds = 0;
businessProduction = 0;
}
float net()
{
return (this->production - this->demand);
}
float businessNet()
{
return (this->businessProduction - this->businessNeeds);
}
};
class town
{
public:
// The array of pointers to each of a our resource objects
resource *resList[TOTALRESOURCES];
// This is the town constructor
town()
{
// Loops through the array and creates a new resource object in each
// the resource constructor assigns the default values of 0.
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
resList[i] = new resource();
}
}
~town()
{
// Loops through the array and deletes each resource object
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
delete resList[i];
}
};
int main()
{
//What do I do here?
for (int i = 0; i < TOTALTOWNS; i++)
{
town townName[i];
}
system("pause");
return 0;
}
So, I'm a software engineering student and I just switched majors so I decided to take some personal time to learn how to code in c++ a bit better. I decided to build a program that can plan the logistics for a videogame called Patrician IV.
I have put about 5 days worth of work into this project and have found some serious problems with my initial code (hard to add new functionality and change stuff around). So I took a step back and am trying to build my classes in a more succinct manner while also being able to loop through each instance of town later in a loop so I can update the demand, production, businessNeeds, and businessProduction values easily. I was copying and pasting about 6 lines of code 40 times before this.
I want to know:
(A) is it possible to do what I want - i.e. can I use enums and a for-loop to construct instances of town.
(B) how to loop through each of the towns so that I can add values to the resource variables.
(C) a third-grade-level explanation of how to use pointers for similar purposes would also be great.
:) THANK YOU!
In your main function, use the same idea as resList to initialize your town objects, so:
town* townName[TOTALTOWNS]
for (int i = 0; i < TOTALTOWNS; i++)
{
townName[i]= new town();
}
Then, I'm guessing you want to give different values for each of the different resources. Switch statements go along with enums well. So I would recommend something like this:
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
switch(i)
{
case WOOD:
townName[EDINBURGH]->resList[WOOD]->demand= yourValue;
break;
case BRICK:
break;
}
}
Or if you're cycling through towns:
for (int i = 0; i < TOTALTOWNS; i = i + 1)
{
switch(i)
{
case EDINBURGH:
break; //etc.
}
}
If you only want to update a single town or resource, depending on how you're organizing everything, you could create something like this. A function that takes your town array and the enum indexes, like this:
updateTownResources(town* (*townName)[TOTALTOWNS], int townEnum, int resourceEnum, int dValue, int pValue )
{
townName[townEnum]->resList[resourceEnum]->demand= dValue;
townName[townEnum]->resList[resourceEnum]->production= pValue;
//etc...
}
int main()
{
std::vector<town*> townArray;
//What do I do here?
for (int i = 0; i < TOTALTOWNS; i++)
{
town* pTown = new(std::nothrow) town;
townArray.push_back (pTown);
}
std::vector<town*>::iterator iter = townArray.begin();
for (;iter != townArray.end(); iter++) {
(*iter); // gives access to individual objects
}
system("pause");
return 0;
}

C++ dereferencing an instance

I'm new to C++ and I'm trying to dry up my code, for example:
void gethit () {
Gert.hitbox(AA.x, AA.damage);
Gert.hitbox(AB.x, AB.damage);
Gert.hitbox(AC.x, AC.damage);
Gert.hitbox(AD.x, AD.damage);
Gert.hitbox(Terbil.x, Terbil.damage);
}
AA, AB, AC, AD and Terbil are all instances of a class called Entity with variables x and damage.
Every time I want to add a new instance I'll have to come into this function and add it manually. I'm trying to add all of the address of the instances to an array like so:
void * p_enemys[10];
p_enemys[0] = &AA;
p_enemys[1] = &AB;
p_enemys[2] = &AC;
p_enemys[3] = &AD;
p_enemys[4] = &Terbil;
Just wondering how I could call a function from the instance via the array, I tried to do
for(int i = 0; i < 10; i++;) {
Gert.hitbox(p_enemys[i].x, p_enemys[i].damage);
}
and g++ compiler spits out: "request for member `damage' in `p_enemys[i]', which is of non-aggregate type `void *'"
I don't really need to use arrays specifically any help is very appreciated.
Changes made, thanks #gldraphael!
vector <Entity*> p_Enemys(10);
void gethit () {
for (int i = 0; i < 10; ++i) {
Entity * ienemy = (Entity*) p_Enemys[i];
Gert.hitbox((ienemy->x), (ienemy->damage));
}
}
You can make an a std::vector as follows:
std::vector <Entity*> p_Enemys(10);
The assigning part remains the same:
p_enemys[0] = &AA;
p_enemys[1] = &AB;
p_enemys[2] = &AC;
p_enemys[3] = &AD;
p_enemys[4] = &Terbil;
You can then loop through the p_enemys as follows:
for(auto i : p_enemys) {
Gert.hitbox(i->x, i->damage);
}
So what was it that you missed?
The array was declared as an array of void*
So, in the loop, p_enemys[i] returned a void*.
Also class/struct members are accessed using a dereferencing operator ->. You used the membership operator . instead.
So this code should have worked instead:
for(int i = 0; i < p_enemys.size(); i++;) { //
Entity * ienemy = (Entity*) p_enemys[i]; // cast the void* into a Entity*
Gert.hitbox(ienemy->x, ienemy->damage);
}
As a general rule, avoid void*s whenever possible.

memory overlapping in an initialization of a class

My problem is I have a header file in which I store all my classes and in my cpp file I have my initializations of these classes, the initialization is not dynamic I have a number of arrays of different classes.
Now the problem is when I started expanding the classes in my header, adding more members and methods,the initialization of 1 specific class start throwing assertions at me of memory overlapping and suggested using memmove() instead of memcpy(), though I use neither of them in that class.
I tried replacing this class with a downgraded version of it that worked in older versions of my source but it still threw the same assertion at me I don't know what part of the code is relevant here is the assertion is being asserted in the initialization of the class without any pointer to what exactly is wrong.
this is my initialization of the class :
Shuriken(cpFloat m,cpVect veloc,cpFloat elast,cpFloat myu) : Spark() , Bang1() , ShurikenFlame()
{
smass = m;
sv = veloc;
se = elast;
su = myu;
ToDraw = false;
Removed = true;
AllocatedBombAnim = false;
DrawFlamedShuriken = false;
DeployFlameBang = false;
PassedLine = false;
hitfruit = false;
FruitIsBeingHit = false;
ToRemoveBody = false;
DummyAdded = false;
HitBossBanana = false;
fruitnum = 11;//11 means it has no fruit
Sec_FlameCounter = 3;
LitShuriken_UVs[0] = CIwFVec2(0, 0);
LitShuriken_UVs[2] = CIwFVec2(1.0/4, 1.0/4);
LitShuriken_UVs[3] = CIwFVec2(1.0/4, 0);
LitShuriken_UVs[1] = CIwFVec2(0, 1.0/4);
Sparkle_UVs[0] = CIwFVec2(0, 0);
Sparkle_UVs[2] = CIwFVec2(1.0/2, 1.0/4);
Sparkle_UVs[3] = CIwFVec2(1.0/2, 0);
Sparkle_UVs[1] = CIwFVec2(0, 1.0/4);
lastPos = cpvzero;
lastAngle = 0;
struct cpVect initShurikenBody_Verts[35] =
{
cpv(-128.01,41.26),
cpv(-58.74,45.42),
cpv(-47.79,32.04),
cpv(-40.06,33.94),
cpv(-20.63,48.29),
cpv(-16.13,55.67),
cpv(-25.33,69.7),
cpv(0,134.67),
cpv(25.34,70.16),
cpv(16.14,55.67),
cpv(20.75,48.1),
cpv(39.98,34.04),
cpv(47.96,32.15),
cpv(58.86,45.38),
cpv(128.01,41.26),
cpv(74.55,-2.82),
cpv(57.95,1.45),
cpv(52.25,-5.19),
cpv(45.16,-26.79),
cpv(45.77,-35.34),
cpv(61.86,-41.64),
cpv(79.1,-108.95),
cpv(20.79,-71.41),
cpv(19.62,-54.33),
cpv(11.91,-51.14),
cpv(-12.02,-51.11),
cpv(-19.64,-54.26),
cpv(-20.81,-71.4),
cpv(-79.11,-108.95),
cpv(-61.87,-41.6),
cpv(-45.77,-35.03),
cpv(-45.18,-26.75),
cpv(-52.23,-5.35),
cpv(-57.88,1.31),
cpv(-74.48,-2.8),
};
struct cpVect initShurikenShape_Verts1[5] =
{
cpv(-128.01,41.26),
cpv(-58.74,45.42),
cpv(-47.79,32.04),
cpv(-57.88,1.31),
cpv(-74.48,-2.8),
};
struct cpVect initShurikenShape_Verts2[5] =
{
cpv(0,134.67),
cpv(25.34,70.16),
cpv(16.14,55.67),
cpv(-16.13,55.67),
cpv(-25.33,69.7),
};
struct cpVect initShurikenShape_Verts3[5] =
{
cpv(47.96,32.15),
cpv(58.86,45.38),
cpv(128.01,41.26),
cpv(74.55,-2.82),
cpv(57.95,1.45),
};
struct cpVect initShurikenShape_Verts4[5] =
{
cpv(79.1,-108.95),
cpv(20.79,-71.41),
cpv(19.62,-54.33),
cpv(45.77,-35.34),
cpv(61.86,-41.64),
};
struct cpVect initShurikenShape_Verts5[5] =
{
cpv(-79.11,-108.95),
cpv(-61.87,-41.6),
cpv(-45.77,-35.03),
cpv(-19.64,-54.26),
cpv(-20.81,-71.4),
};
struct cpVect initShurikenShape_Verts6[4] =
{
cpv(-47.79,32.04),
cpv(-40.06,33.94),
cpv(-52.23,-5.35),
cpv(-57.88,1.31),
};
struct cpVect initShurikenShape_Verts7[4] =
{
cpv(-20.63,48.29),
cpv(-16.13,55.67),
cpv(16.14,55.67),
cpv(20.75,48.1),
};
struct cpVect initShurikenShape_Verts8[4] =
{
cpv(39.98,34.04),
cpv(47.96,32.15),
cpv(57.95,1.45),
cpv(52.25,-5.19),
};
struct cpVect initShurikenShape_Verts9[4] =
{
cpv(45.16,-26.79),
cpv(45.77,-35.34),
cpv(19.62,-54.33),
cpv(11.91,-51.14),
};
struct cpVect initShurikenShape_Verts10[4] =
{
cpv(-12.02,-51.11),
cpv(-19.64,-54.26),
cpv(-45.77,-35.03),
cpv(-45.18,-26.75),
};
struct cpVect initShurikenShape_Verts11[10] =
{
cpv(-40.06,33.94),
cpv(-20.63,48.29),
cpv(20.75,48.1),
cpv(39.98,34.04),
cpv(52.25,-5.19),
cpv(45.16,-26.79),
cpv(11.91,-51.14),
cpv(-12.02,-51.11),
cpv(-45.18,-26.75),
cpv(-52.23,-5.35),
};
for(int i=0;i<5;i++)
ShurikenShape_Verts1[i] = initShurikenShape_Verts1[i];
for(int i=0;i<5;i++)
ShurikenShape_Verts2[i] = initShurikenShape_Verts2[i];
for(int i=0;i<5;i++)
ShurikenShape_Verts3[i] = initShurikenShape_Verts3[i];
for(int i=0;i<5;i++)
ShurikenShape_Verts4[i] = initShurikenShape_Verts4[i];
for(int i=0;i<5;i++)
ShurikenShape_Verts5[i] = initShurikenShape_Verts5[i];
for(int i=0;i<4;i++)
ShurikenShape_Verts6[i] = initShurikenShape_Verts6[i];
for(int i=0;i<4;i++)
ShurikenShape_Verts7[i] = initShurikenShape_Verts7[i];
for(int i=0;i<4;i++)
ShurikenShape_Verts8[i] = initShurikenShape_Verts8[i];
for(int i=0;i<4;i++)
ShurikenShape_Verts9[i] = initShurikenShape_Verts9[i];
for(int i=0;i<4;i++)
ShurikenShape_Verts10[i] = initShurikenShape_Verts10[i];
for(int i=0;i<10;i++)
ShurikenShape_Verts11[i] = initShurikenShape_Verts11[i];
for(int i=0;i<35;i++)
ShurikenBody_Verts[i] = initShurikenBody_Verts[i];
}
I am using Visual Studio 2010 with Marmalade SDK and I am writing in C++.
Thanks for any help,
Anton
Ok, so if we assume that ShurikenShape_Verts1 is either a regular C style array or a C++ style std::array and has the type cpVect, and cpVect is a POD struct:
for(int i=0;i<5;i++)
ShurikenShape_Verts1[i] = initShurikenShape_Verts1[i];
can be copied as:
memcpy(ShurikenShape_Verts1, initShurikenShape_Verts1,
sizeof(initShurikenShape_Verts1));
However, I have made some assumptions here, since you haven't posted enough code. I'd hate to start a "can post this, can you post that" type thread, asking for a large number of other bits of your code, but it also means that I may not have answered the question correctly, since I don't know for sure that your cpVect is indeed a POD struct, for example.
(I'd submit a comment but I don't have enough of a stackoverflow "reputation" to do so:-()
I would seriously stand back and look at why you are trying to copy this stuff to start with. Copying lots of stuff is comparatively slow. Far better to use a pointer to the existing array or a reference, which depends on your style.
If by "cpVect is just 2 floats made into a vector" you mean vector, then don't use memcpy or whatever. This is just going to give you heap issues later. Remember that these work by allocating behind the scenes. If you use memcpy you are going to get two objects pointing to the same content, and when the first goes out of scope that content will be freed.

Strange errors: EXC_BAD_ACCESS in my class

Here is my code:
typedef struct TItemSelector{
ItemSelectFrame* pItems[2];
} SItemSelector;
class item {
public:
void expMethod();
SItemSelector itemSelector_;
UILayerButton* startBtn_;
};
void item::expMethod(){
startBtn_ = new UILayerButton();
for (i = 0; i < 3; i++) {
itemSelector_.pItems[i] = new ItemSelectFrame();
}
startBtn_->callMethodA();
}
void UILayerButton::callMethodA()
{
this->callMethodB();
}
void UILayerButton::callMethodB()
{
}
On this->callMethodB();, a "EXC_BAD_ACCESS" occoured.
After that I found a work-around:
class item {
public:
void expMethod();
SItemSelector itemSelector_;
SItemSelector itemSelector2_; // work around
UILayerButton* startBtn_;
};
Then everything goes well... I just don't know what happened, but callMethodB() is just an empty method, there's nothing to do with it.
I'm using Apple LLVM 3.1, default setting.
UPDATE: Fixed my code.
In this code:
for (i = 0; i < 3; i++) {
itemSelector_.pItems[i] = new ItemSelectFrame();
}
you are writing over the end of itemSelector_.pItems because pItems is an array of length 2 but you are writing 3 elements.
That then overwrites startBtn_ which happens to appear immediately after itemSelector_ in memory. And that explains the error when you subsequently read the now corrupted startBtn_.
Either change your loop termination test, or increase the length of pItems. I can't tell which one is the correct solution, but clearly you will know.