View Full Version : Do you actually use dynamic memory?
Najdorf
2005.08.27, 10:21 PM
Looks to me it's quite difficult and not really important in most games...
Do you use it?
OneSadCookie
2005.08.27, 10:24 PM
What kind of question is this?
I'm assuming you mean new/malloc/+alloc? In which case, what answers did you expect other that "yes, always"?
Najdorf
2005.08.27, 10:30 PM
Yeah I mean new and delete.
Couldnt you just make arrays "big enough"? I mean, rarely games have memory problems, much more often performance problems.
OneSadCookie
2005.08.27, 11:06 PM
There's no reason dynamic memory need be any more performance-problematic than making lots of global arrays "big enough"...
There's no way to use inheritance in C++, or any Objective C without using dynamic memory, so that alone will swing most people.
Making lots of global arrays "big enough" has its own problems. Karl Berg's .obj loader took that approach, and it liked to make about 50MB per object. Then when you made a global array of "enough" objects (say, 20) then all of a sudden you're using more than a GB of RAM....
Najdorf
2005.08.28, 12:48 AM
hmmm... ok...
looks like my games are way too simple for me to appreciate this stuff.
akb825
2005.08.28, 02:19 AM
I'm voting "often" since I use arrays and stack objects when it's advantuous to do so (like I know that I'm going to need only 3 values for a vector, or I have an object that I won't be moving around), but I use heap memory otherwise.
akb825
2005.08.28, 02:26 AM
There's no way to use inheritance in C++, or any Objective C without using dynamic memory, so that alone will swing most people.
I have C++ objects that use inheritance and virtual functions that are created on the stack rather than the heap. You use Type object(parameters) to create such object, and they work fine. Objective C, however, doesn't let you create such objects.
OneSadCookie
2005.08.28, 05:49 AM
oh, inheritance will "work", you just can't use dynamic polymorphism without at least taking the address of the object, and taking the address of objects on the stack is asking for pain ;)
Malarkey
2005.08.28, 08:08 PM
Looks to me it's quite difficult and not really important in most games...
Do you use it?
Uh, actually, I use it a lot in whatever project I'm working on, be it a simple game, a tool, or a commercial level game.
akb825
2005.08.28, 11:24 PM
oh, inheritance will "work", you just can't use dynamic polymorphism without at least taking the address of the object, and taking the address of objects on the stack is asking for pain ;)
As in you store a bunch of subclasses as superclasses (for a container or what-not)? For that, pointers are definitely best. I usually only use stack/data objects for temporary objects or instance variables that are initialized only on the initialization of the class they are in.
aarku
2005.08.28, 11:37 PM
I only use behemoth switch statements in my programming. Maybe one unsigned long long to track the state, and that's it.
-Jon
davidhelgason
2005.08.28, 11:51 PM
That must have been One Clever Switch , and One Very Well Packed Int :)
-> http://otee.dk/forum/viewtopic.php?t=510
How many man-hours did actually go into it?
d.
I only use behemoth switch statements in my programming. Maybe one unsigned long long to track the state, and that's it.
-Jon
Yeah, that's how REAL programmers do it.
aarku
2005.08.29, 04:24 PM
That must have been One Clever Switch , and One Very Well Packed Int :)
-> http://otee.dk/forum/viewtopic.php?t=510
How many man-hours did actually go into it?
d.
I'd estimate 100.
-Jon
akb825
2005.08.29, 05:06 PM
GIgantic switch statements have their place, but I try to avoid them unless I think it's necessary (such as with data streams)
Najdorf
2005.08.31, 07:49 AM
In obj-c do you use some kind of lists that do dynamic memory for you or do you have to free up space yorself and do pointer operations and stuff?
ThemsAllTook
2005.08.31, 10:25 AM
You can do either. There's NSMutableArray for dynamically resizable lists, or you can roll your own. Cocoa's memory management system uses a retain/release architecture: Each object has a reference count, which starts at 1 when the object is allocated, is incremented by retain, and is decremented by release. When it drops to 0, the memory is freed. For the parts of your code that don't directly use Cocoa, you can also do things the good old-fashioned C way with malloc/realloc/free and raw pointers.
- Alex Diener
Andrew
2005.08.31, 12:16 PM
Check out this tutorial (http://www.macdevcenter.com/pub/a/mac/2001/07/27/cocoa.html) on memory management in Cocoa.
Najdorf
2005.08.31, 01:36 PM
You can do either. There's NSMutableArray for dynamically resizable lists, or you can roll your own. Cocoa's memory management system uses a retain/release architecture: Each object has a reference count, which starts at 1 when the object is allocated, is incremented by retain, and is decremented by release. When it drops to 0, the memory is freed
cool, that's also how blitzmax works.
It's obvious that I'm just starting CO227 (the advanced C++ class focusing on pointers, OO programming, and the.. uh, advanced stuff :)) because I have no idea how to work all the dynamic memory things being mentioned. I have some small idea of what malloc does, but beyond that, it looks a whole lot like jibberish to me at the current time.
akb825
2005.09.07, 03:52 PM
Quicky on dynamic memory: (main benefit of having an object on the heap (or dynamic memory) is that it outlives the function you create it in)
C:
The function malloc takes the number of bytes you want to allocate to the heap and returns a pointer to that memory. It returns a void pointer, so you will need to cast that to the particular type you need.
If you want to have an struct myObject (typedefed as myObject) on the heap, you have a myObject pointer (myObject *) and you have to call malloc passing in sizeof(myObject) as the parameter. The call would look like this.
myObject *object = (myObject *)malloc(sizeof(myObject));
If you want to have an array of myObject objects, you just multiply the size. Lets say you want an array of 5 of them:
myObject *objects = (myObject *)malloc(sizeof(myObject)*5);
You can then access each of the five objects as you would a normal array (as in from objects[0] to objects[4])
Objects created on the heap must also be destroyed by you, so when you're done, you must call free(object); (same applies for both)
C++:
Instead of calling malloc and free in C++, you use new and delete (though you can still use malloc and free if you want). Basically, instead of having a pointer then calling malloc with a size, you call new then a type. For example, with the same myObject:
myObject *object = new myObject;
then you call delete with it to destroy it when you're done.
delete myObject;
If your object has a constructor that takes parameters, you just call that constructor with the object.
myObject *object = new myObject(parameters);
With an array, you just add brackets with the number of items.
myObject = new myObject[5];
just remember that you also need a bracket after delete
delete[] myObject;
And there you have it! Dynamic memory. (not as hard as you thought, huh? :p)
So if I have a particle system and I want to have a nice dynamic memory set up going for storing the particles (each being two vectors and a float wrapped up into a nice class), how would I code that into my class?
Here's my guess but I just learned this all from reading that and a few past experiences (that almost never went as planned):
class ParticleSystem
{
...
private:
Particle *particles;
};
...
ParticleSystem::ParticleSystem(int numParticles)
{
particles = new Particle[numParticles];
}
ParticleSystem::~ParticleSystem()
{
delete[] particles;
}
akb825
2005.09.07, 04:13 PM
That would work fine. FYI, with C++ classes, you can just put all your private variables and methods directly under the declaration, since the first unnamed field is automatically private.
I know but I usually have a lot of public functions that I like to list above them. I just forgot to put the public: in the example there. That's part of the ... :)
One more question. What would I have to do to resize my particle size?
akb825
2005.09.07, 04:41 PM
You would need to create a temporary array with new, copy the elements, then delete the old array and set the pointer of the new array to the private variable.
So something like this?
Attempt 2:
void ParticleSolver::Resize(int numParticles)
{
Particle *temp = new Particle[numberOfParticles];
memcpy(temp, particles, (numberOfParticles * sizeof(Particle)));
delete[] particles;
particles = new Particle[numParticles];
memcpy(particles, temp, (numberOfParticles * sizeof(Particle)));
delete[] temp;
numberOfParticles = numParticles;
}
Also, how could I check to see if that function actually works as I want it to (i.e. doesn't just keep eating memory)?
Edit: I'm leaving this here for example purposes but I realized it wouldn't work because I'm making a pointer to a pointer and if I remove the first pointer, the new pointer has no data.
void ParticleSystem::Resize(int numParticles)
{
Particle *tempStorage = particles;
delete[] particles;
particles = new Particle[numParticles];
particles = tempStorage;
delete[] tempStorage;
}
Fenris
2005.09.07, 05:20 PM
Actually, the first fields are protected, not private. :)
akb825
2005.09.07, 05:33 PM
No, that would likely cause a crash. You have to copy it particle by particle. First of all, you will need to have a copy method that will copy all the data from one particle to another. Let's call this copyData. You will also need to store the size of the old array (when you first create it). Let's call it particleSize. You will need to do something like this:
void ParticleSystem::Resize(int numParticles)
{
Particle *tempStorage = particles;
particles = new Particle[numParticles];
workingSize = (numParticles < particleSize) ? numParticles : particleSize;
for (int i = 0; i < workingSize; ++i)
particles[i].copyData(tempStorage[i]);
delete[] tempStorage;
}
akb825
2005.09.07, 05:35 PM
Actually, the first fields are protected, not private. :)
I stand corrected. :)
What exactly would go into the CopyData() function that you have in that code? Remember that I'm just learning all this memory management stuff (and it's hard).
Plus you were right about it crashing :). I tried it on my own (just to see) and it didn't work too well. This is my entire .cpp file for the class (if you have time, let me know if anything else is going to go wrong so when I get home from work I can fix it):
/*
* ParticleSolver.cpp
*
* Copyright 2005 SimReality Games. All rights reserved.
*
*/
#include "ParticleSolver.h"
extern int screenWidth, screenHeight;
extern GLint myList;
ParticleSolver::ParticleSolver()
{
particles = new Particle();
ptr = particles;
}
ParticleSolver::~ParticleSolver()
{
delete[] particles;
}
ParticleSolver::ParticleSolver(int numParticles)
{
particles = new Particle[numParticles];
numberOfParticles = numParticles;
ptr = particles;
}
void ParticleSolver::Resize(int numParticles)
{
Particle *temp = new Particle[numberOfParticles];
memcpy(temp, particles, (numberOfParticles * sizeof(Particle)));
delete[] particles;
particles = new Particle[numParticles];
memcpy(particles, temp, (numberOfParticles * sizeof(Particle)));
delete[] temp;
numberOfParticles = numParticles;
ptr = particles;
}
void ParticleSolver::MakeNewParticle()
{
Resize(numberOfParticles + 1);
ptr += (numberOfParticles - 2) * sizeof(Particle);
ptr->position.x = screenWidth / 2;
ptr->velocity.y = -1;
}
void ParticleSolver::UpdateParticles(float frameRate)
{
int i = 0;
ptr = particles;
for(i = 0; i < numberOfParticles; i++)
{
ptr->position.x += ptr->velocity.x;
ptr->position.y += ptr->velocity.y;
ptr->position.z += ptr->velocity.z;
if(ptr->position.y < screenHeight)
ptr->position.y = 0;
ptr += sizeof(Particle);
}
}
void ParticleSolver::DrawParticles()
{
int i = 0;
ptr = particles;
for(i = 0; i < numberOfParticles; i++)
{
glPushMatrix();
{
glScalef(10,10,10);
glTranslatef(ptr->position.x,
ptr->position.y,
ptr->position.z);
glCallList(myList);
}
glPopMatrix();
ptr += sizeof(Particle);
}
}
akb825
2005.09.07, 06:09 PM
copyData does just that: it copies all the variables from the Particle in the parameter to the particle that it's called from. It should be declared as
void copyData(Particle &particle)
and just have a bunch of lines such as data = particle.data. If you have arrays, be sure to copy the elements in a loop.
To clarify the necessity, since you have an array of Particle objects in ParticleSystem, they all call the default constructor, so you will need to copy the data after the fact. (hence this method)
Edit: to clarify, this is supposed to be a member function of Particle.
Ok, just one C++ question: what does this line do? I'm confused by the : and ? and < in the middle of it.
workingSize = (numParticles < particleSize) ? numParticles : particleSize;
OneSadCookie
2005.09.08, 12:02 AM
x = b ? m : n;
is exactly equivalent to
if (b)
{
x = m;
}
else
{
x = n;
}
AnotherJake
2005.09.08, 12:12 AM
The conditional operator ? was originally a C feature I believe. It's often cryptic to read, and it's easy to write pointless code with too, so it's usually best to avoid using it. Nice to know when you need to read other people's code though.
akb825
2005.09.08, 12:17 AM
I find it preferable for simple things such as that, since it's much quicker and uses less space than an if statement. If you get into complicated tertiary statements, it can get ugly, though.
I think the tertiary operator may have originated before C, possibly with Fortran or before. IIRC, it was the only choice for a while. (not 100% sure about that, though)
PowerMacX
2005.09.08, 12:45 AM
Someone should split this thread.
LongJumper
2005.09.08, 01:19 AM
Just a tip on you're particle code as it stands now...
As you know, a particle system constantly is losing particles and adding new particles, and doing this rather quickly depending on what your particle system is trying to represent. If you were to try that on your current code, your computer would probably explode.
Why? Well, say you have so many particles and you add a couple hundred more, you are copying over an entire array, deleting an entire array, allocating a new larger array, copying over an entire array then deleting an entire array... a lot of times. I know this thread is about dynamic memory, but this is a textbook example of when NOT to use dynamic memory.
Also, I'm not sure why you need a display list for every single one of your particles, a billboarded quad is the best way to do it, that way you aren't pushing/popping the modelview matrix a billion times a frame, and calling scaling/translating functions each particle, each frame.
Furthermore, you are allowed to use [] on dynamically allocated arrays. I'm not sure on what kind of speed differences you get by using the [] operators vs. incrementing the pointer(+ function overhead of sizeof), maybe OSC or someone else at that level can speak on that one, I know I'd certainly like to know which is quicker. If you're already using an incrementing variable to loop thru the number of particles, might as well use the [] operators at least to make it a bit more clear to yourself while learning.
akb825
2005.09.08, 02:06 AM
I'd imagine the difference using [] would be negligible at best. Using particles[i] should be the same as doing particles + i. So basically, it would be like the difference between i + 1 and i++ numerically. Also, sizeof isn't a function, it's technically an operator. If you wanted to be a stickler, there is also a difference between ++i and i++ or ++particles and particles++, since post incrementation also creates a temporary variable. (why I always use ++i instead of i++ now ;)) Essentially, it's nothing you'd notice unless you had about 20 billion particles or so, and even then 1 second out of an hour isn't going to be very noticeable. ;) (numbers completely made up, but you get the idea :p)
vBulletin® v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.