Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


stack vs heap


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
31 replies to this topic

#1 akira2000   Members   -  Reputation: 137

Like
0Likes
Like

Posted 15 February 2013 - 06:38 AM

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 



Sponsor:

#2 Hodgman   Moderators   -  Reputation: 31181

Like
9Likes
Like

Posted 15 February 2013 - 07:49 AM

Yes, you should use automatic (stack) lifetimes where possible, and heap lifetimes where you have to.
n.b. with your example of using new, it returns a pointer to an object (in Java, every "object"-type variable is implicitly a pointer, but in C++ you need the "*")
{
  Object* obj1 = new Object();//obj1 is a local variable, that is a pointer to a heap allocated object
  Object& obj2 = *(new Object()); //a reference is pretty much the same thing as a pointer, but looks like it isn't ;)
  Object obj3;//local variable (stack allocation)
  delete obj1;
  delete &obj2;
  delete &obj3;//this is an error! It wasn't made with 'new' so you can't use 'delete'
}//obj3 deleted here automatically due to the stack unwinding

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

You can't manually "free" an object from the stack. Stack frames are pushed and popped for each "block" of code (basically every set of "{ ... }"). Whenever a "}" is reached, all the stack variables that were created in that block are destroyed. So there are never any holes.
 
For an example of where stack allocation isn't applicable, imagine a function that makes a new monster appear:
Monster* SpawnMonster()
{
  Monster m;
  return &m;//error! m is created with the same scope as this function. When the function returns, m is "deleted".
}
 
Monster* SpawnMonster()
{
  Monster* m = new Monster();
  return m;//correct, but someone has to delete this at some point, otherwise you've got a memory leak
}
shared_ptr<Monster> SpawnMonster()
{
  return shared_ptr<Monster>(new Monster());//also correct. This acts more like what you're used to in Java. When there are no more shared_ptr's that reference the Monster, it will automatically be deleted.
}

Edited by Hodgman, 15 February 2013 - 07:54 AM.


#3 NightCreature83   Crossbones+   -  Reputation: 2937

Like
1Likes
Like

Posted 15 February 2013 - 09:13 AM

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, 15 February 2013 - 09:14 AM.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, Mad Max

#4 Álvaro   Crossbones+   -  Reputation: 13684

Like
2Likes
Like

Posted 15 February 2013 - 09:30 AM

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.



#5 SiCrane   Moderators   -  Reputation: 9629

Like
0Likes
Like

Posted 15 February 2013 - 10:22 AM

Another place you will often want heap allocation is when you are using polymorphism.

#6 akira2000   Members   -  Reputation: 137

Like
0Likes
Like

Posted 15 February 2013 - 10:27 AM

OK biggrin.png  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 :) 



#7 TMarques   Members   -  Reputation: 189

Like
1Likes
Like

Posted 15 February 2013 - 10:47 AM

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.


Tiago.MWeb Developer - Aspiring CG Programmer

#8 akira2000   Members   -  Reputation: 137

Like
0Likes
Like

Posted 15 February 2013 - 11:03 AM

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 ??? 



#9 Cornstalks   Crossbones+   -  Reputation: 6991

Like
2Likes
Like

Posted 15 February 2013 - 11:15 AM

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.


[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#10 TMarques   Members   -  Reputation: 189

Like
1Likes
Like

Posted 15 February 2013 - 11:18 AM

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.


Tiago.MWeb Developer - Aspiring CG Programmer

#11 Aliii   Members   -  Reputation: 1447

Like
1Likes
Like

Posted 15 February 2013 - 11:18 AM

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). 



#12 Cornstalks   Crossbones+   -  Reputation: 6991

Like
2Likes
Like

Posted 15 February 2013 - 11:19 AM

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

Fixed that for you ;)


[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#13 Álvaro   Crossbones+   -  Reputation: 13684

Like
0Likes
Like

Posted 15 February 2013 - 02:02 PM

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.



#14 BigWinston   Members   -  Reputation: 103

Like
0Likes
Like

Posted 15 February 2013 - 02:17 PM

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!!



#15 MarlboroKing   Members   -  Reputation: 192

Like
0Likes
Like

Posted 15 February 2013 - 03:06 PM

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, 15 February 2013 - 03:08 PM.


#16 Khatharr   Crossbones+   -  Reputation: 3031

Like
0Likes
Like

Posted 15 February 2013 - 10:26 PM

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?
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

#17 Álvaro   Crossbones+   -  Reputation: 13684

Like
0Likes
Like

Posted 15 February 2013 - 10:45 PM

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>'.

#18 akira2000   Members   -  Reputation: 137

Like
0Likes
Like

Posted 15 February 2013 - 11:17 PM

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 ???



#19 King Mir   Members   -  Reputation: 2032

Like
0Likes
Like

Posted 16 February 2013 - 01:39 AM

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.



#20 Khatharr   Crossbones+   -  Reputation: 3031

Like
0Likes
Like

Posted 16 February 2013 - 03:25 AM

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.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS