# stack vs heap

This topic is 1794 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello.

I'm working as java programmer and just now starting to learn c++ and irrlicht (want to create games as a hobby ;) ).

I am completely confused by stack vs heap issue.

What is the advantage of using heap? Isn't it MUCH faster and more efficient to create variales on stack and pass them by reference.

What I mean is:

Object obj = new Object();

VERSUS

Object obj;

method1(&obj)

I am also confused by memory managment in c++. When stack object is freed is there a memory "hall" in stack.

Thanks

##### Share on other sites

Hello.

I'm working as java programmer and just now starting to learn c++ and irrlicht (want to create games as a hobby ;) ).

I am completely confused by stack vs heap issue.

What is the advantage of using heap? Isn't it MUCH faster and more efficient to create variales on stack and pass them by reference.

What I mean is:

Object obj = new Object();

VERSUS

Object obj;

method1(&obj)

I am also confused by memory managment in c++. When stack object is freed is there a memory "hall" in stack.

Thanks

Generally in C++ if you want by reference passing of variables you define this in the function header not in it's use.

void functionByReference(const Object& obj);
void functionByPointer(const Object* obj); //In compiled code(asm) there is no difference between this call and the one above it, the compiler does see this differently though.
void functionByValue(const Object obj);

//Both are called as follows
Object object;
functionByReference(object); //This call is faster then the one below it
functionByValue(object);

functionByPointer(&object); //You have to use the address operator here because the function is expecting a pointer to an object


Usually you only feed a function a "&<variable>" when you only have a stack value and the function wants a object that's passed by pointer. Even when the variable is an output parameter this is expressed in the function header and not in it's use.

Edited by NightCreature83

##### Share on other sites

The language in NightCreature83's post is not completely clear, so let me clarify. There is no notion of "function header": He probably meant to say "function prototype".

C++ has no notion of output parameter. If you want to use a parameter for output, you can make it a reference or a pointer. If you make it a reference, the code that calls the function will be indistinguishable from passing by value or by const' reference. If you made it a pointer, the code would look just the way the OP posted (with the &'). That's why I usually prefer to get a pointer for variables I intend to modify.

##### Share on other sites
Another place you will often want heap allocation is when you are using polymorphism.

##### Share on other sites

OK   Now it's MUCH clearer.

As I see it now, I should use stack vars if and only if it's life span does NOT need to exceed the scope of it's creation {}.

Also, a "little" advantage of heap vars is that I can free them in the "middle" of the scope, thus the memory usage is a little smaller.

Ok! I will use stack vars where I can !

Thank you all for the valuable answers :)

##### Share on other sites

Furthermore, stack memory should be avoided when dealing with large sets of data since most operating systems gives a limit for stack allocation (something in the order of 10mb from my experience), so if you try to declare an data array of size bigger than 10mb for example, your program will most likely crash.

Thought it would be worth mentioning since it's a bug very difficult to catch. I don't know what are the workarounds for that so I only use heap for large data allocation.

##### Share on other sites

Furthermore, stack memory should be avoided when dealing with large sets of data since most operating systems gives a limit for stack allocation (something in the order of 10mb from my experience), so if you try to declare an data array of size bigger than 10mb for example, your program will most likely crash.

Thought it would be worth mentioning since it's a bug very difficult to catch. I don't know what are the workarounds for that so I only use heap for large data allocation.

0.o are you sure about this one? In java, for example, I do sometimes have objects of this size. When I work with images, pdfs...

So I should create objects on stack only if their size < X ???

##### Share on other sites

Furthermore, stack memory should be avoided when dealing with large sets of data since most operating systems gives a limit for stack allocation (something in the order of 10mb from my experience), so if you try to declare an data array of size bigger than 10mb for example, your program will most likely crash.

Thought it would be worth mentioning since it's a bug very difficult to catch. I don't know what are the workarounds for that so I only use heap for large data allocation.

0.o are you sure about this one? In java, for example, I do sometimes have objects of this size. When I work with images, pdfs...

Java isn't allocating that memory on the stack. It's allocating it on the heap.

So I should create objects on stack only if their size < X ???

If you are dealing with large objects (like large arrays), you should allocate them on the heap. Besides, I've typically found that if I need a (potentially) large array, it's probably a dynamically sized array too, so allocating it on the stack at compile time makes very little sense.

##### Share on other sites

You can test it yourself, start by declaring a small vector and keep increasing it's size.

float hum[100000];

float hum[1000000];

float hum[10000000];

Eventually you'll reach a "segmentation fault" error.

I can't ensure you of this fact, since I could have done some wrong compiler configuration or my O.S (Ubuntu) deals with memory management in a different way, so I'll leave to more experienced programmers to elaborate on this. I had this issue once and it was very hard to figure it out.

Let me know what yo find.

##### Share on other sites

In java, for example, I do sometimes have objects of this size

You can have. Java uses the heap too.

Your "X" varies from system to system, plus depends on how much stuff you have on the stack already(e.g are you using recursions or not).

##### Share on other sites

You can test it yourself, start by declaring a small vectorarray and keep increasing it's size.

Fixed that for you ;)

##### Share on other sites

Even if you use the heap, there is rarely a reason to do so by directly writing new' and delete' in your program. For instance, if I need a large array (or if I am not too sure what size it will have) I use std::vector, which will allocate its data on the heap, but it does so using RAII (an acronym that never made sense to me, but it means the destructor takes care of things). If I need polymorphism, I use a smart pointer (unique_ptr, most likely) that also uses RAII.

There are still ways to leak memory when you program this way, but it's hard.

##### Share on other sites

Another pitfall to look out for (one that seems obvious but have seen before)  - when passing by reference and also maybe using locals is never return a reference to local data when returning from a function.  Of course, the data will be popped off the stack and won't exist any more.  Reads will provide "bad" data (i.e. whatever happens to be on that stack location) and writes can really screw things up!!

##### Share on other sites

You can try what Hodgman said by something like this (I just find this a bit more clear!)

class MyClass
{
public:
MyClass()
{
memset( &m_szName, 0, sizeof(m_szName) );
strcat_s( m_szName, "I'm an object!" );
}

~MyClass()
{
}

public:
char m_szName[64];
};

void DoSomethingHere()
{
printf( "DoSomethingHere()\n" );
}

void DoSomethingElseHere( MyClass var )
{
printf( var.m_szName );
printf( "\n" );
}

void DoAnotherThingHere( MyClass var )
{
memset( var.m_szName, 0, sizeof(var.m_szName) );
strcat_s( var.m_szName, "Rewriting var.m_szName" );
printf( var.m_szName );
printf( "\n" );
}

int _tmain(int argc, _TCHAR* argv[])
{
DoSomethingHere();

{
MyClass obj;
DoSomethingElseHere( obj );
}

DoAnotherThingHere( obj );

Sleep( 50000 );

return 0;
}



And yes, there are certain benefits you can abuse by using code blocks like above (eg; a large command table).

Visual Studio gave me an error that obj is undefined when trying to call "DoAnotherThingHere", letting me know that "obj" would no longer exist after it has executed passed that end-codeblock.

Along the way, you'll understand when to allocate on the stack or the heap.

Edited by MarlboroKing

##### Share on other sites
Are you sure about that overflow-by-array problem? I would think the compiler would just make the stack large enough. Isn't required stack length included in the module header?

##### Share on other sites

Isn't required stack length included in the module header?

I am not entirely sure what you mean by that, but no: The stack size is usually determined by the OS. For instance, if you are using the bash shell in Linux, you can set the stack size for new processes using `ulimit -s <number_of_kilobytes>'.

##### Share on other sites

About shared_ptr. I read now that that Bjarne consider this as bad idea and this is considered as bad c++ design pattern. Anyone can put some light on this.

About unique_ptr. I do NOT want to write managed code. Is unique_ptr managed code ???

##### Share on other sites

Some compilers allow segmented stacks, which do not have limits on size and the stack can grow just like heap variables. Some can also convert large stack arrays to heap arrays.

##### Share on other sites

Is unique_ptr managed code ???

No, it's just a different kind of smart pointer. unique_ptr is more or less an upgraded version of auto_ptr.

##### Share on other sites

Generally the whole point of the heap is to allow you to have precise control over when you allocate and deallocate memory. Obviously you can't just exit function calls constantly to free memory, especially if something runs in a tight loop and parts of the reserved memory need to stay in use and others need to be freed as you go. For games this is an obvious one since you get things like "permanent" entities in the world that need to be removed when they are no longer used.

I've noticed most people here recommend using smart pointers simply because it adds things like reference counting which is minute overhead for the benefit of the memory freeing itself when no longer needed, but, honestly, it all comes down to your needs. There's no strict reason you HAVE to use a smart pointer, in fact you can free allocate and free things and null pointers whenever you like, but its on your head if something gets missed.

##### Share on other sites

if your writing a real time game, I would recommend an entirely different approach:

code should be C, not C++. No OO, no virtual methods, no mallocs (new, etc), no polymorphism. none of that slow stuff!

vars should be passed by reference with the fastcall convention and no stack frame.

the size limit for the stack segment supposedly went away years ago (at least in windows OS), so you should be able to declare huge arrays locally in a procedure without exceeding stack segment size. If its still an issue, simply do a malloc at procedure start and a free at procedure end.

whenever possible, declare data structures as global statics. instead of new-ing and disposing a bunch of objects for NPCs all the time, have a global array[MAXNPCS] with an active field in the struct. always use arrays vs linked lists. in general, always do whats fast, not whats considered "correct" by non-game programming standards. if its the "correct" way to do things in the real programming world, odds are its totally wrong for high performance real time games.

do you have any idea exactly what happens (at the instruction set and clock cycle count level) when you create an object? talk about SLOW code!

remember OO was invented for people who couldn't write ADT (abstract data type) style non-spaghetti code, and as a slicker way to encapsulate variant records and procedural variables. It has nothing to do with writing games that run fast. May make it easier (for some) to write code, but slower code on average, unfortunately.

like most things in game development, there's the easy way and the fast way to do it. if you code each line with clock cycles in mind form the get go, you'll have very little optimization to do at the end.

##### Share on other sites

if you code each line with clock cycles in mind form the get go, you'll have very little optimization to do at the end.

This is absolutely true, because you'll probably never finish your game. You probably won't even get 5% of it done by the time you (hopefully) realized you've seriously screwed up and are prioritizing horribly wrong. And by then, your code will be so defunct you might as well start over from scratch. So yes, very little optimization to do at the end indeed, because you won't reach the end.

FWIW, optimizations should be focused on algorithmic optimizations. Optimizing a single line of code (or a bunch of lines individually) will likely have very little effect on your program's performance (the rare exceptions are incredibly tight loops that are known to be significant bottle necks (known after profiling)).

And Norman, you're insanea complete troll if you seriously think you shouldn't use any dynamic memory allocation. Yeah, definitely a troll. Not even gonna try to respond to your post anymore.

##### Share on other sites
Once somebody who coded every line with clock cycles in mind went through one of my functions and optimised it. He did an amazing job. Of course, it was completely unreadable.

Then I realised that the function didn't need to be called and deleted it.