the title is a bit too general. Let me get to it straight.
I have an application with a large number of potential structures, called Player.
So I thought, lets make an array of pointers to Player, due to the fact that usually you wont need all the players and you will safe up dynamic memory compared to directly allocating an array with the maximum size, so (C++):
Player* a[max];
for loop
a[i] = new Player
end
vs
Player* a;
a = new Player[max]
The first example is what I use in a function. Every time you call that function, it allocates the next pointer in the array. Everything works, but the strange thing is that sometimes one of the pointers seems to lose its reference to the heap memory. When I have 2 players and I allocate 10, it works, but after a while (several frames guaranteed) it displays "-1.#J" as the value of a float in that Player structure, which I suppose means that it is an undefined value.
I could not post the entire code (would be too much), and I checked for all other possible bugs, but I could not find one. I start presuming that it has to do with the fact that I allocate the memory using new in a function in a different .ccp file (so different obj file). Could this be the case? And can you use array of pointers for this situation?
I could be horrible be wrong with my ideas about memory saving using this method. Please give me advice on how to do it properly if so.
Thanks.
(EDIT)
the code for spawning the player (I dont know how to do the layout, sorry for that):
void SpawnPlayer(float xpos, float ypos, float angle, unsigned short ammo[WP_TOTAL], unsigned char weapon)
{
player[game.players] = new Player;
// Properties
player[game.players]->pos[0] = xpos;
player[game.players]->pos[1] = ypos;
player[game.players]->angle = angle;
player[game.players]->dir[0] = 0.0f;
player[game.players]->dir[1] = 0.0f;
player[game.players]->speed = PL_SPEED;
player[game.players]->health = PL_HEALTH;
player[game.players]->shoot = true;
player[game.players]->shootwait = 0;
unsigned char i;
CLoops(i, 0, WP_TOTAL)
{
player[game.players]->ammo[i] = ammo[i];
}
player[game.players]->weapon = weapon;
// Model
float cx = cos(angle) * PL_RADIUS, cy = sin(angle) * PL_RADIUS;
player[game.players]->model.vertexcnt = 4;
player[game.players]->model.vertex = new float[8];
player[game.players]->model.vertex[0] = xpos - cx - cy ;player[game.players]->model.vertex[1] = ypos - cy + cx;
player[game.players]->model.vertex[2] = xpos - cx + cy ;player[game.players]->model.vertex[3] = ypos - cy - cx;
player[game.players]->model.vertex[4] = xpos + cx - cy ;player[game.players]->model.vertex[5] = ypos + cy + cx;
player[game.players]->model.vertex[6] = xpos + cx + cy ;player[game.players]->model.vertex[7] = ypos + cy - cx;
player[game.players]->model.texcoord = new float[8];
player[game.players]->model.texcoord[0] = 0.0f;player[game.players]->model.texcoord[1] = 0.0f;
player[game.players]->model.texcoord[2] = 1.0f;player[game.players]->model.texcoord[3] = 0.0f;
player[game.players]->model.texcoord[4] = 0.0f;player[game.players]->model.texcoord[5] = 1.0f;
player[game.players]->model.texcoord[6] = 1.0f;player[game.players]->model.texcoord[7] = 1.0f;
core.CCreateModel(player[game.players]->model, CMODEL_TRISTRIPS, CMODEL_DYNAMIC);
// AI
player[game.players]->target = PL_MAXCNT;
player[game.players]->move = 0;
// Add global counter
game.players++;
}
Why not use a vector of Player object pointers?
std::vector<Player*> vec;
Then, when you want to allocate a new player, do:
vec.push_back(new Player);
Here, the problem with your code may be that there is a chance of any Player stored in an array getting over written. But, using vector, you can use const iterators and hence, make sure that they are not getting changed when you don't want them to.
Also, you don't have to worry about allocating a constant size.
Also, if your Player object contains any member pointers, make sure that you don't pass any Player object by value or do assignment using them. If that is the case, you might want to write your own copy constructor and assignment operator so that shallow copy does not occur.
Related
I'm having some problems with polymorphism I have a superclass of CEntity, and a subclass of unit type, I am dynamic casting and removing and emplacing a new entity of the dynamic casts type at its place, I have the opposite problem of my previous question.
Problem is the values being set are not changing, it remains with default values, it appeared to work before but now it has stopped working, I'm not sure what has caused the issue.
specifically buildsetup, sets the x-y-z values of the unit subclass's x,y,z, but when I look inside the vector the values remain unchanged, this is strange because it does actually manage to change the values for whether the unit is alive or not.
void builder(int no, string in , int top, int bot, CTeam &team, string owner, string original)
{
for (int i = top; i <= bot; i++)
{
EntityUnit* a;
a = dynamic_cast<EntityUnit*>(AWorld.EntitiesVector[i]);
a->unit_alive;
if (a->unit_alive == false)
{
float x = Player.returncity_add().cit_ret_X();
float y = Player.returncity_add().cit_ret_Y();
float z = Player.returncity_add().cit_ret_Z();
cout << "X:" << x;
cout << "Y:" << y;
cout << "Z:" << z;
float cost = MainAB.UnitTemplates[no]->UDRetCost();
float health = MainAB.UnitTemplates[no]->UDRetMaxHealth();
float damage = MainAB.UnitTemplates[no]->UDRetStrength();
float speed = MainAB.UnitTemplates[no]->UDRetSpeed();
float buildtime = MainAB.UnitTemplates[no]->UDRetBuildTime();
int popcost = MainAB.UnitTemplates[no]->UDRetPop();
a->set_owner(owner);
setmodel(i, x, y, z); // takes an xyz by ref and sets the model
to them then changes the model's localz by -10
Units[i]->SetSkin(setskin(owner, original));
a->BuildSetup(x, y, z, health, damage, speed, buildtime, cost, popcost);
team.inc_popcount(a->UDRetPop());
a->set_unit_alive(true);
sBuildUnit.play();
AWorld.EntitiesVector.erase(AWorld.EntitiesVector.begin() + i);
AWorld.EntitiesVector.emplace(AWorld.EntitiesVector.begin() + i, new EntityUnit(a));
AWorld.EntitiesVector[i]->set_x(x);
AWorld.EntitiesVector[i]->set_y(y);
AWorld.EntitiesVector[i]->set_z(z);
break;
}
}
Entity build setup
void EntityUnit::BuildSetup(float x, float y, float z,float _health, float _damage, float _speed, float _buildtime, float _cost, int _popcost)
{
unit_x = x;
unit_y = y;
unit_z = z;
unit_health[0] = _health;
unit_health[1] = _health;
unit_damage = _damage;
speed = _speed;
buildtime = _buildtime;
cost = _cost;
CUnitType = NA;
pop_req = _popcost;
}
After static debugging it, it most definately emplaces a new unit with the updated -is_alive, and while a's values change at the point of unitbuild, when its emplaced all x,y,z's return to 9999, which was what it was when they were pushed on the vector.
When you call
AWorld.EntitiesVector.erase(AWorld.EntitiesVector.begin() + i);
you destroy the object pointed to by a. The subsequent reference to it on the next line is Undefined Behavior, and anything is possible.
I'm not sure why you erase the entity, then try to put a new one in the same place. If you structure your code right you should be able to just reuse the existing entity (pointed to by a) without the erase and emplace calls.
Ok, Apparently the problem was it was totally unnecessary to erase/emplace, as I get what you mean now returning a pointer, it edited the value... odd it didn't work last time.
Im kind of stuck with this problem
i created this function but for some reason i can only move the object to the right of the Player.
If i try to move the object to the Left of the Player is goes right.
here is my approach:
int Speed = 8;
int x = Player_x - Mouse_x;
int y = Player_y - MOuse_y;
float deg = atan(y / x);
float erg_x = Speed * cos(deg);
float erg_y = Speed * sin(deg);
erg_x/y are the numbers i use at the end to move the Object.
Please help me :)
As explained here, atan only works in the first and fourth quadrant. Since going left involves the second quadrant, this isn't going to work.
As such, you'll want to change
float deg = atan(y / x);
to
float deg = atan2(y, x);
I am currently programming a game on C++ and am working with the SDL 2.0 library.
I am attempting to disect a 32x32 image from a texture to store as a tile and am attempting to recreate it from the pixels of a texture. When I run this code and attempt to edit the Uint32* by a for loop, I can edit it but once I try to creat the image, I get a heap corruption.
I currently have this code running:
Uint32* pixels = (Uint32*)m_pSprite->GetPixels();
int pixelCount = (m_pSprite->GetPitch() / 4) * m_pSprite->GetHeight();
int tileOffset = 0;
int spriteSheetOffset = 0;
int widthOffset = m_pSprite->GetWidth();
Uint32* tilePixels = new Uint32(32);
for (int y = 0; y < 32; y++)
{
tileOffset = (y * 32);
spriteSheetOffset = (y * widthOffset);
for (int x = 0; x < 32; x++)
{
tilePixels[tileOffset + x] = pixels[spriteSheetOffset + x];
}
}
int tilePitch = 32*4;
SDL_Texture* texture = SDL_CreateTexture(backBuffer.GetRenderer(), SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, TILE_WIDTH, TILE_HEIGHT);
I can see that there is something wrong with the Uint32* variable and that this is obviously not a best practice but I am still wrapping my head around what can and cannot be done, and what is the best way etc.
Does anyone have an explanation of what could be happening?
Uint32* tilePixels = new Uint32(32);
This is dynamically allocating a single Uint32, and initializing/constructing it to the value 32. It seems you want a 32*32 array of those. Try this:
Uint32* tilePixels = new Uint32[32*32]; // brackets allocate an array
Although, since the size of your array is static (known at compile-time), it would be best to just use a stack-allocated array instead of a dynamic one:
Uint32 tilePixels[32*32];
See if that fixes it.
string Player::CalcAsteroid(int _mass)
{
vector<BaseObject*>* tempObjects = GameState::GetObjects();
asteroid = "";
SetRadius(_mass / 100);
if (_mass < 100)
SetRadius(1);
///////////////////////////////////////////////
// Nested for loops to draw a circle (asteroid)
///////////////////////////////////////////////
// x^2/a^2 + y^2/b^2 = 1
Player* p = dynamic_cast<Player*> ((*tempObjects)[0]);
int asteroidRadius = p->GetRadius();
double consoleRatio = 4.0 / 3.0; // Console characters do not have uniform H and W, so lets store the console ratio (4:3)
double a = consoleRatio*asteroidRadius; // The width is shorter than the height, so we'll multiply the ratio to the X radius (a)
double b = asteroidRadius; // The height need not change from the init radius
// Loop though each row...
for (int y = (int)-asteroidRadius; y <= asteroidRadius; y++)
{
// and each column.
for (int x = (int)floor(-consoleRatio*asteroidRadius); x <= consoleRatio*asteroidRadius; x++)
{
double d = (x / a)*(x / a) + (y / b)*(y / b); // Equation of a circle (see above)
if (d > 0.90 && d < 1.1)
{
asteroid += (char)178; // The solid border (using gradient ASCII code)
}
//else if (d <= 1.1)
//{
//asteroid += 176; // The fill interior
//}
else
{
asteroid += " ";
}
}
asteroid += '\n';
}
asteroid.replace(asteroid.size() / 2 - (name.size() / 2), name.size(), name); // Putting the name of the player in the center of the asteroid.
return asteroid;
}
So I am attempting to re-size the player's object (an asteroid) in console. However I seem to be getting memory leaks, a ton actually. Each seems to be related to this function call.
SetPicture(CalcAsteroid(GetMass()).c_str());
The definition of which being here
void SetPicture(const char * const _picture){ picture = _strdup(_picture);CalcWH(); }
CalcWH(); simply calculates the width and height of the image in characters for collision data.
Dropbox link for full solution.
Thank you all in advance! Let me know if there is anything I can do to make my question more clear or whether or not I have enough information. I'm new to this site and I wish to follow good question habits.
The reason for a memory leak is the usage of _strdup. This allocates memory for the new string. It is your responsibility to free the memory using free somewhere in your code. According to the code you posted, you are not calling free anywhere.
https://msdn.microsoft.com/en-us/library/y471khhc.aspx
As noted by the above link:
The _strdup function calls malloc to allocate storage space for a copy of strSource and then copies strSource to the allocated space.
My advice is to get out of the business of calling _strdup, and just use a std::string. There is little reason for a C++ application to use functions such as strdup.
I'v tried to solve a memory leak in the GLU callback by creating a global variable but now it dos not draw anything:
GLdouble *gluptr = NULL;
void CALLBACK combineCallback(GLdouble coords[3], GLdouble *vertex_data[4],
GLfloat weight[4], GLdouble **dataOut)
{
GLdouble *vertex;
if(gluptr == NULL)
{
gluptr = (GLdouble *) malloc(6 * sizeof(GLdouble));
}
vertex = (GLdouble*)gluptr;
vertex[0] = coords[0];
vertex[1] = coords[1];
vertex[2] = coords[2];
for (int i = 3; i < 6; i++)
{
vertex[i] = weight[0] * vertex_data[0][i] +
weight[1] * vertex_data[0][i] +
weight[2] * vertex_data[0][i] +
weight[3] * vertex_data[0][i];
}
*dataOut = vertex;
}
basically instead of doing malloc each time in the loop (thus the memory leak) im using a global pointer, but this doesn't work (drawing to the screen not working) which means dataOut is not receiving the vertex data pointed to by my pointer. Why would using malloc to a pointer created in the function work any different than a global variable?
Thanks
You allocate the data only once -- but GLUtesselator needs more than one set of data at a time!
What you do here, is putting all the vertex data into a single place in memory, where in the original code, you had memory per vertex. GLUtesselator needs more then one vertex to function properly.
You do call
void gluDeleteTess(GLUtesselator *tessobj);
...afterwards, do you?
Most likely the reason is that something outside of your callback is holding on to the returned data across calls to combineCallback(), and subsequent calls to combineCallback() clobber now the data from the older calls.
Looking at the code, you need to rewrite this, there's a few things wrong which shows the inherent lack of understanding pointers and using call-by-reference parameter such as dataOut, secondly, there is no checking on the call to malloc which can fail and WILL fail, the code blindly assumes that the memory is available, thirdly, you have redundant pointer variables used such as vertex and gluptr for a reason. You are actually trying to build up a block of memory by copying the contents from gluptr to vertex, and use the coords pointer-to-block of data type of 'GLDouble', then build up the vertex block of memory... and finally assign it back to dataOut...forgive me if I misunderstand but read on...
This is the code that has removed redundant variables as shown below and fixes up the lack of checking for a NULL pointer...
GLdouble *gluptr = NULL;
void CALLBACK combineCallback(GLdouble coords[3], GLdouble *vertex_data[4],
GLfloat weight[4], GLdouble **dataOut)
{
if((*dataOut) == NULL)
{
(*dataOut) = (GLdouble *) malloc(6 * sizeof(GLdouble));
}
if (*dataOut != NULL){
/* PASSED MEMORY ALLOC! */
(*dataOut)[0] = coords[0];
(*dataOut)[1] = coords[1];
(*dataOut)[2] = coords[2];
for (int i = 3; i < 6; i++)
{
(*dataOut)[i] = weight[0] * vertex_data[0][i] +
weight[1] * vertex_data[0][i] +
weight[2] * vertex_data[0][i] +
weight[3] * vertex_data[0][i];
}
}
}
The last parameter when calling this function combineCallback is a call-by-reference parameter, hence the usage of the double asterisk..
I must ask this, is dataOut definitely a fixed size of 6 elements? if so then the parameter would need to be tweaked up...to make it look like *(*dataOut[6])... looking at it top off my head (it's late and past my bedtime...)