Archived

This topic is now archived and is closed to further replies.

jedi2832

Allocating Memory in C++

Recommended Posts

jedi2832    122
My question is, whats the use of allocating memory in the pointers, whats with the use of new and delete, and there is stack and the heap, i''m totally confused in the pointer section, i know what pointer is and what it does, just not the allocating memory stuff and the stack and heap. thx for answering

Share this post


Link to post
Share on other sites
DariusX    122
Well, memory is where everything on the computer is held, including all your program stuff (code, resources, graphics, etc). So you need to allocate some for your program to use.

The new and delete commands are basicly to help you make allocating memory easier.

See, new can allocate you ANY type of memory, by using the following code:

void *pointer = new dataType;

''dataType'' would be replace with whatever kind of data type you need allocated (int, char, long, etc).

Then of course, the allocated data has to be released back to the system, and that''s where delete comes in:

delete[] pointer;

So there ya go, I hope helped.

THIS book rocks.

3D gaming Haven Opening soon.

Share this post


Link to post
Share on other sites
rypyr    252
Please ignore most of DariusX's response.

1) his use of delete is incorrect in his example. delete[] is only used for memory that was allocated as an array

2) you should never do :

void* pointer = new ....;

This destroys type safety in the worst way. Not only can you very easily forget what pointer points to (is it ints? a single char? a complicated object?), but to use the pointer in any useful way, you have to cast it to its correct type.

3) he does not address your questions about heap and stack

You can think of it this way:

- there are things in your program which you may want to allocate dynamically (i.e. at runtime) versus setting up memory beforehand.

I'll give you a simple example is: if a wizard player has spells to summon creatures, you have no idea which spell he will cast. If he casts a "summon skeleton" spell, you have to allocate memory for a skeleton creature and then put him into the game. But the player could also cast a "summon goblin army" spell, which means you'll have to allocate memory for a large number of goblins instead. You don't want to have to allocate all the memory at once in your program to cover all cases. What you need to do is:

- when the player casts the spell, allocate the memory you need
- when the creature(s) die(s), then de-allocate the memory

Hopefully this gives you a good understanding of why you need to dynamically allocate memory. To do this in C++, you use new/delete.

When you use new/delete as they are, you will be allocating memory on the heap (unless you're using more advanced techniques like your own memory manager, etc). Think of it this way: the heap is just one giant blob (or heap!) of memory that you can allocate and de-allocate to your heart's content in the program.

Now the stack: The stack is a smaller (and usually quicker!) region of memory that is used within a function to store temporary variables (i.e. variables that will be automatically de-allocated once the end of the function is reached. For example:


void goo(int x) { cout << x << endl; }
void foo() {
int v = 5; // v is placed on the stack
goo(v);
} // v is de-allocated from the stack here

void main() {
foo();
}


The variable v is allocated on the stack upon entering foo() but is de-allocated when foo() exits.

Hope this helps.

Regards,
Jeff

[edited by - rypyr on April 28, 2003 5:20:09 PM]

Share this post


Link to post
Share on other sites
NewbieGamer    122
Hi,
I am not an expert, but i shall try to explain what i understand.
Added to the previous post by DariusX, whenever you use variables in your class/functions they are requests to the system for storing some data and they need to be given some place to live. The C/C++ compiler will allocate the "living" areas for the variables based on how you declare them.
e.g. if you consider the following code

void main()
{
int x; //Local variable
char y[20]; //Local variable

// do something here and that is it.
}

The x and y are called local to the function and therefore will be allocated "living" quarters in a community called "Stack". [Just a name for the memory block that holds temporary/local variables]. These variables cannot be accessed from anywhere outside the scope of the function and therefore have a short lifespan. They are volatile and "die" as soon as you get out of the function. So stuff that goes into the "Stack" lives only for a short span. One other point to note here is that for such variables, the entire amount of space required is allocated. so x will be given sizeof(int) bytes depending on system and the variable "y" will be allocated 20xsizeof(char) bytes. This space will be claimed back automatically.

Consider the following piece of code.
void main()
{
int *pX = NULL;
pX = new int[5];
}
Here during the first line [declaration] pX is not allocated any "living" quarters other than 2 Bytes for storing the address of the variable pX. You only inform the compiler that you may store any number of elements later on. So in the next line when you say new int[5], the system will create 5 entries, each capable of holding an integer and then return the address of the first element to pX. Now, this area that was just allocated should be managed by the programmer; what this means is that, you have to free up the "new"ed elements when you are done. Why? because, the "living" quarters that was just allocated for pX was done from a different community called "Heap". That is the characteristic of "new"/"malloc"/"calloc"/et al. The way to free up the allocated memory is to use "delete". When programmers forget to free up memory that they no longer use/need, or delete the wrong pointer you have all sorts of funny behaviour in the system...... and can even lead to Blue Screen of Deaths.

Hope i did not try to explain something that you already knew. If it is confusing and need more explanation, i can try to do that.

Have a good time conquering pointers!!!
V.

Share this post


Link to post
Share on other sites
NewbieGamer    122
Hi,
I had a delay between when i started my reply and actually posted it. I therefore, could not take into account rypyr''s response. rypyr''s response sounds even more "practical" to the kind of applications that you will be dealing with and should be more helpful. Good one rypyr.

Cheers!!!
V

Share this post


Link to post
Share on other sites
rypyr    252
NewbieGamer: You''re answer was also quite good and touched a little more on how to actually use new, which I neglected.

DariusX: Sorry if I offended you, I guess I was a little harsh. However, I felt much of what you stated was either erroneous or misleading. Posting for the sake of posting (without a solid understanding of the topic) can potentially lead to disaster.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Alrighty lets get down to the nitty gritty of it all.


In order to make any type of program (including games) you need to have memory. This is why when you purchase a new computer you get to select how much memory you want to have. This type of memory is called RAM (random access memory) and provides you a buffer of sorts when you run your program.

Every time you make a variable you use up some ram for instance:

int myInt; (on a windows 32 system this will take up 32bits of RAM)
char myChar (on a windows 32 system this will take up 8 bits of RAM).

The above are examples of "static memory". Static memory itself never changes when you hit the compile button. It''ll never take up more memory or less memory than it''s ment to (theoretically speaking. I don''t want to confuse you with alignment issues quite yet).

Now this creates a problem because often when we make applcations we don''t always know how large an array needs to be in order to fit all the data. For instance lets say you and your buddy Jim are writing papers for a class. The teacher did not say how long your papers needed to be. So the next day you come to school with a paper that''s 10 pages long while Jim comes to school with a paper that''s 1 page long. The question then becomes if you had to write a program to load the text up into a buffer and print it out on screen could you possibly know ahead of time the maximum ammount of pages everyone in your class would write? It''s impossible to know this ahead of time (unless your Miss Cleo)!

Fortunately we have an alternative to static memory and it''s called dynamic memory. This type of memory doesn''t remain constant, you can change the size of an array from 32 to 50 and then back to 10 if need be. How do we use this type of memory? new and delete of course!

But before we can use the memory we need to create a pointer to point at the memory we are about to allocate.....
int *integerArray = 0; now we can create an integer array integerArray = new int[32]; (if we were to do this statically we''d type in int integerArray[32]. So what exactly does new do? Well it goes through your memory and looks for a slot large enough to hold the array. In our case the size of an int is 4 bytes, and the number of ints we want to allocate is 32...so 4*32 = 128. So new goes looking for 128 bytes of free memory to use, when it finds a spot with enough memory available it returns the address. Now your pointer points to a spot in RAM that''s large enough to store 32 integers.

Now because we are allocating this dynamically we have to clean up our own mess before the program exits. You see the program itself knows nothing about the dynamically allocated memory it just sees a pointer to memory. So if we don''t use delete on the pointer before exiting we''ll create a "Memory Leak". A memory leak happens when you allocate a bunch of memory and never release it. It can cause your computer to slow down alot or even crash, so we want to make sure that this gets cleaned up. So before we exit our program we call "delete [] integerArray;" note that the []''s are only used when you''ve allocated an array, if you used new to allocate a single integer or character or any other singlular thing then you''d just use "delete integer;" instead.

This should''ve answerd the majority of your questions. As for the stack and heap for now you don''t need to be worried about them, progress on into your learning and you''ll be ready to tackle these another day.

Share this post


Link to post
Share on other sites
DariusX    122
rypyr: You didn''t offend me. heh... But I''m not posting just to post, I could do that in a general chat forum. lol

I do know about new and delete, just not stacks and heaps.

THIS book rocks.

3D gaming Haven Opening soon.

Share this post


Link to post
Share on other sites
rypyr    252
quote:
Original post by DariusX
I do know about new and delete, just not stacks and heaps.



Using:

void* pointer = new dataType;
delete[] pointer;

show me that you really don''t know new/delete too well yet

Regards,
Jeff

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
A stack is a section of memory reserved for the execution of a program. All of a program''s static memory is kept in the stack. Meaning if you have a function like this:

int main()
{
int num1;
int num2;
}

When you call the function, eight bytes (four for each int) are reserved on the stack. The size of the stack grows and shrinks during the program execution, as each function you call must reserve some space on the stack, and that memory is freed when the function returns. This is why recursive algorithms are bad, and can cause the program to run out of stack space.

The heap is how dynamic memory is managed. It asks the OS to reserve a certain amount of memory outside of the stack. This is good when you don''t know exactly how much memory you will need at compile time, but is bad because you can forget to free the memory with calls to delete.

int main()
{
int* num1 = new int[100];
}

This reserves four bytes on the stack, because all pointers (int* in this case) are four bytes long. This also reserves 400 bytes on the heap, for 100 4-byte ints. Unlike memory on the stack, memory on the heap is not released when the function returns, so you have to be careful to delete it after you are done with it.

Share this post


Link to post
Share on other sites
Sneftel    1788
quote:
Original post by DariusX
I do know about new and delete, just not stacks and heaps.

If you don''t know about stacks and heaps, you don''t know about new and delete.


How appropriate. You fight like a cow.

Share this post


Link to post
Share on other sites
CWizard    127
I'll try to give a short summary on what the stack is. The purpose of the stack is to store temporary data in LIFO (Last-In-First-Out) manner. In the lower levels, its most important use is to store the return address when you make a function call. In C/C++/etc it is also used to store local variables.

Here's how it works. When the OS starts the program, it allocates a chunk of memory, typically some 0.25 to 1 megabyte, and sets the program's (or rather, the thread's) stack pointer pointing to the end of it:

-----FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF-----
^
stack pointer
This shows an empty stack. Like this when it is used:

-----FFFFFFFFFFFFFFFFFFFFFFFFFUUUUUUUUUUUUUUUUUUUUUUUU-----
^
free stack stack pointer used stack

To work better, we look only at the end of the stack. Note that the memory at and below the stack pointer is occupied, and the memory above it is free to use:

Mem Addr Data
..........: ........
0x50002080: 00000000
0x50002084: 00000000
0x50002088: 00000000
0x5000208C: 00000000
0x50002090: ........ <-- stack pointer, points to after the stack

When a function has been called and it shall return, the processor must know where to continue execution. Therefor when the jump to the function is made, the address of the instruction after the jump is stored on the stack:
:

Mem Addr Data
..........: ........
0x50002080: 00000000
0x50002084: 00000000
0x50002088: 00000000
0x5000208C: 40024288 <-- stack pointer
0x50002090: ........
When entering the function, we have have a declaration int a = 1, b = 2;, which a pushed on the stack. This is done by substracting the total size of all local variables from the stack pointer, in this case sizeof(int) * 2 == 8:

Mem Addr Data
..........: ........
0x50002080: 00000000
0x50002084: 00000001 <-- stack pointer
0x50002088: 00000002
0x5000208C: 40024288
0x50002090: ........
When the function is done, it need to restore the stack, so it will add (in this case) 8 to it. When it is about to return execution to where the function was called, the processor pops the return address of the stack, simply reading whatever is at the stack pointer's address, then incement it by 4:

Mem Addr Data
..........: ........
0x50002080: 00000000
0x50002084: 00000001
0x50002088: 00000002
0x5000208C: 40024288
0x50002090: ........ <-- stack pointer
The old data will still be there, but it is still free for use.

EDIT: Oops! Some temporary insanity caused me to say that the stack was FIFO. (thanks idko)




[edited by - CWizard on April 28, 2003 9:46:35 PM]

Share this post


Link to post
Share on other sites
idko    122
Briefly(not really):

Stack is used by the cpu for temporary data at the machine level.

Heap is where the program''s data is stored.

The program Code is stored in a special place called the Code segment.

The stack is organized in a LIFO(last in, first out) manner. For example, the stack is empty and you put a 10 in it. So now the stack has a 10. And then you add a 20 to it, so now the stack is holding 20,10. And you add 5 to it, so now the stack is holding 5,20,10.

In assembly, this is called a push. You push data into the stack and to retrieve the data in the stack, you pop. Since it is a Last in, First out, the most recent data pushed into the stack is the first data that gets popped out of it.

So if you,

push 10
push 20
push 5
pop

Then the data you get back is 5. If you pop again, you get 20 and so on.

The stack size is limited and when you run out of space, all hell breaks loose. The Heap is larger though. The heap is only limited by the system ram. Windows takes care of it for you through virtual memory.

Now, about pointers and stuff...

Just memorize this and you will always remember how pointers work.

* stands for "what''s in"
& stands for "the address of"

remember those two and you will be all set.

so:

int *p; means that p is a pointer to an integer address.

*p = 5; assigns 5 to the location where p is pointing to.
&p gives you the address of p itself
and p gives you the location in memory where 5 is being stored.

catfish?

Now about allocating memory...

The heap is where your program data is stored. And that is where all your declared variables exist. But the life of your variables depends on their scope. By this, I mean that the data is acknowledge by the system as long as it is still being used.

For example:

int y;

void main(void)
{
for(int i=0;i<100;i++)
{
int x;
}
}

In this scenario, i will exist as long as the loop is running. Once the loop ends, i will be removed from the heap. While the loop is running, the heap reserves a spot for i. The variable x is being created and destroyed each cycle of the loop and the variable y exists in the heap as long as the program is still running.

How does this fit with allocating? Well, programs can get complex, and sometimes a programmer won''t know for sure how much memory he or she will need to use. So during the program execution, the program will allocate or reserve memory space in the heap. When the program no longer needs that space, it will deallocate or free it so that it can later be used for something else.

I think everyone else answered the new and delete pretty well, but just for crap and giggles, here it goes...

The new keyword will allocate a spot for you in the heap, and the delete keyword will free it. This is a nifty way to get variables without having to use malloc() or free(). But remember that this is a C++ feature and it doesn''t work on C.

Be sure to remember and I emphasize this, use delete for normal variables and use delete[] for arrayed variables.

Share this post


Link to post
Share on other sites
CWizard    127
idko, local variables are not allocated from the heap. They are pushed on the stack. Of course, the stack itself was at some point allocated from the heap (by the OS). The stack is also subject to virtual memory, at least on x86 architecture. There are some interesting special processors where the stack is located inside the processor, but that is a different story.

Btw, thanks for alerting me for incorrectly saying the stack was FIFO.

Share this post


Link to post
Share on other sites
idko    122
^_^ And that is what I tried to say with, "Windows takes care of it for you through virtual memory." But I admit, I was a bit vague with that. It''s tricky business. And thank you for reminding me that local variables are stored closer to the cpu. I meant to say that somewhere.

And, your explanation of the stack was very good.

Share this post


Link to post
Share on other sites
NewbieGamer    122
Reading these posts serves as a refresher course.... Thanks to all the contributions ....
While we mention the usage differences in delete and delete[] i think it should also be mentioned that the new/delete and malloc/free should be matched as well.
So don''t mix new/free or malloc/delete. This is only when you are in a world [c++] and have the freedom to choose new or malloc/calloc.



Cheers!!!
V!

Share this post


Link to post
Share on other sites
evillive2    779
I just made a bookmark to this thread. My thanks to all of the posters, most of these were really well written and great for both newbies and for those of us who could use a refresher every now and then. Now to link this with all of those new/delete vs malloc/free threads...

Share this post


Link to post
Share on other sites
hey guys, help me out and finish the discussion.
let me run down a noob problem im having right now.

I have a struct LandVert



      

struct LandVert
{
float x, y, z ; // The transformed position for the vertex.

float nx, ny, nz; //the normal for the square

DWORD color; //the diffuse color of the vertex, also stores alpha.

float tu,tv; // The vertex texture coordinates.

//


};
//here i initialize the pointer

LandVert* vertices = 0; //pointer to vertices array




In a call to the object that contains the struct i need to new
numofVerts vertices, so i need an array of my struct with numofVerts elements.



HRESULT TListAuthor::MakeTListAuthor(int numofVerts)
{

vertices = new LandVert[(numofVerts - 1)];

}


Later on i attempt to manipulate the components of the struct



vertices[0].x = -1.0f;
vertices[0].y = 2.0f;
vertices[0].tu = 0.0f;
vertices[0].tv = 0.0f;

vertices[1].x = 1.0f;
vertices[1].y = 2.0f;
vertices[1].tu = 1.0f;
vertices[1].tv = 0.0f;

vertices[2].x = -1.0f;
vertices[2].y = 0.0f;
vertices[2].tu = 0.0f;
vertices[2].tv = 1.0f;

vertices[3].x = -1.0f;
vertices[3].y = 0.0f;
vertices[3].tu = 0.0f;
vertices[3].tv = 1.0f;

vertices[4].x = 1.0f;
vertices[4].y = 2.0f;
vertices[4].tu = 1.0f;
vertices[4].tv = 0.0f;

vertices[5].x = 1.0f;
vertices[5].y = 0.0f;
vertices[5].tu = 1.0f;
vertices[5].tv = 1.0f;


for (int i = 0; i < numofVerts; i++)

{

vertices[i].color = 0xFFFFFFFF;
vertices[i].nx = 0.0f;
vertices[i].ny = 1.0f;
vertices[i].nz = 0.0f;
vertices[i].z = -5.0f;


}




later on i create the V Buffer

and then finally draw



g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);


g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);




g_pd3dDevice->SetFVF(UNTRANS_CUSTOMVERTEX);

g_pd3dDevice->SetStreamSource(0,g_pVBuff,0 , sizeof(LandVert));

g_pd3dDevice->SetTexture(0,g_texture);

g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,2);

g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);



when i create my array of structs statically it renders fine,
but when i try to create the array dynamically nothing renders.
the reason i included the drawing code is because the sizeof operators and any possible conflicts between
sizeof(Struct) and sizeof (pointertoStruct)


anyone mind helping out,

*edit* just wanted to pint out that the code compiles,
i have debug code that lets me know the VertexBuffer and Texture are being created, thx for any help, just cant figure it out.

Dreddnafious Maelstrom

"If I have seen further, it was by standing on the shoulders of Giants"

Sir Isaac Newton


[edited by - Dreddnafious Maelstrom on May 1, 2003 5:40:02 PM]

[edited by - Dreddnafious Maelstrom on May 1, 2003 5:49:24 PM]

Share this post


Link to post
Share on other sites
rypyr    252
Sorry you weren''t very clear what you are trying to do.

Are you trying to dynamically allocate a number of LandVert objects?

Share this post


Link to post
Share on other sites
yes, i have a struct defined and im trying to dynamically create an array of them.

Im also uncertain how to refer to them later in code and am trying to do it as:

vertices[num].attribute = value.

it compiles and doesnt throw any exceptions, i just cant find my error. when i create the array statically it renders no problem, which is why i think im handling the memory allocation wrong.

[edited by - Dreddnafious Maelstrom on May 1, 2003 5:53:28 PM]

Share this post


Link to post
Share on other sites
rypyr    252
It looks fine, the way you access the array later. I think you're allocating the memory fine.

Where do you send your vertices into the buffer? Could your problem be this line?

g_pd3dDevice->SetStreamSource(0,g_pVBuff,0 , sizeof(LandVert));

Don't you want to replace that with numVertices*sizeof(LandVert).

Also, where do you delete your objects? Remember to use delete[]...

Regards,
Jeff

[edited by - rypyr on May 1, 2003 6:41:36 PM]

[edited by - rypyr on May 1, 2003 6:45:22 PM]

[edited by - rypyr on May 1, 2003 6:47:21 PM]

Share this post


Link to post
Share on other sites