Tarquila
Tarquila

Reputation: 1207

When do you worry about stack size?

When you are programming in a language that allows you to use automatic allocation for very large objects, when and how do you worry about stack size? Are there any rules of thumb for reasoning about stack size?

Upvotes: 14

Views: 4586

Answers (19)

Christoffer
Christoffer

Reputation: 12910

  1. When the code you've written for a PC suddenly is supposed to run on a mobile phone
  2. When the code you've ported to run on a mobile phone suddenly is supposed to run on a DSP

(And yes, these are real-life snafus.)

Upvotes: 2

INS
INS

Reputation: 10820

You start to worry about stack size when:

  • when your program crashes - usually these bugs tend to be weird first time you see them :)
  • you are running an algorithm that uses recursion and has user input as one of its parameters (you don't know how much stack your algorithm could use)
  • you are running on embedded platforms (or platforms where each resource is important). Usually on these platforms stack is allocated before process is created - so a good estimation about stack requirements must be made
  • you are creating objects on the stack depending on some parameters modifiable by user input (see the sample below)
  • when the code executed in a thread/process/task is very big and there are a lot of function calls that go deep into the stack and generate a huge call-stack. This usually happens in big frameworks that combine a lot of triggers and event processing (a GUI framework; for example: receive_click-> find_clicked_window-> send_msg_to_window-> process_message-> process_click-> is_inside_region-> trigger_drawing-> write_to_file-> ... ). To put it short, you should worry about call-stack in case of complex code or unknown/binary 3rd party modules.

sample for modifiable input parameters:

in my_func(size_t input_param)
{
  char buffer[input_param];
  // or any other initialization of a big object on the stack
  ....
}

An advice:

  • you should mark the stack with some magic numbers (in case you allocate it) and check if those magic numbers will be modified (in that case the stack will not be enough for the task/thread/process and should probably be increased)

Upvotes: 0

anon
anon

Reputation:

I never worry about it. If there is a stack overflow, I will soon know about it. Also, in C++ it is actually very hard to create very large objects on the stack. About the only way of doing it is:

struct S {
   char big[1000000];
};

but use of std::string or std::vector makes that problem go away.

Upvotes: 4

Jack V.
Jack V.

Reputation: 1381

I have had problems running out of stack space when:

  • A function accidentally calls itself
  • A function uses recursion to a deep level
  • A function allocates a large object on the stack, and there is a heap.
  • A function uses complicated templates and the compiler crashes

Provided I:

  • Allocate large objects on the heap (eg. using "auto_ptr foo = new Foo" instead of "Foo foo")
  • Use recursion judiciously.

I don't normally have any problems, so unfortunately don't know what good defaults should be.

Upvotes: 0

sharptooth
sharptooth

Reputation: 170469

You worry about it when you write a callback that will be called from threads spawned by a runtime you don't control (for example, MS RPC runtime) with stack size at the discretion of that runtime. Somehow like this.

Upvotes: 0

user230821
user230821

Reputation: 1123

Only time really is when you are threading and have to define it yourself, when you are doing recursion or when for some reason you are allocating to the stack. Otherwise the compiler takes care of making sure you have enough stack space.

CreateThread by default only allocates 0x100000 bytes for the stack.

Upvotes: 2

Igor Zevaka
Igor Zevaka

Reputation: 76500

I don't. Worrying about this things whilst writing programming normal things is either a case of premature pessimization or premature optimization. It's pretty hard to blow things up on a modern computer anyway.

I once wrote a CSV parser and whilst playing around with trying to get the best performance I was allocating hundereds of thousands of 1K buffers on the stack. The performance was stellar but the RAM went up to about 1GB from memory from normal 30MB. This was due to each cell in the CSV file had a fixed size 1K buffer.

Like everyone is saying unless you are doing recursion you do not have to worry about it.

Upvotes: 1

shoosh
shoosh

Reputation: 78914

When do you worry about stack size?

Never.

If you have stack size problems it means you're doing something else wrong and should fix that instead of worrying about stack size.
For instace:

  • Allocating unreasonably large structures on the stack - don't do it. allocate on the heap.
  • Having a ridiculously long recursion. I mean in the order of painting an image and iterating over the pixels using recursion. - find a better way to do it.

Upvotes: 3

Charles Eli Cheese
Charles Eli Cheese

Reputation: 783

You usually can't really have large objects on the stack. They almost always use the heap internally so even if they are 'on the stack' their data members are not. Even an object with tons of data members will usually be under 64 bytes on the stack, the rest on the heap. The stack usually only becomes an issue these days when you have lots of threads and lots of recursion.

Upvotes: 2

Steve Jessop
Steve Jessop

Reputation: 279225

Played this game a lot on Symbian: when to use TBuf (a string with storage on the stack), and when to use HBufC (which allocate the string storage on the heap, like std::string, so you have to cope with Leave, and your function needs a means of failing).

At the time (maybe still, I'm not sure), Symbian threads had 4k of stack by default. To manipulate filenames, you need to count on using up to 512 bytes (256 characters).

As you can imagine, the received wisdom was "never put a filename on the stack". But actually, it turned out that you could get away with it a lot more often than you'd think. When we started running real programs (TM), such as games, we found that we needed way more than the default stack size anyway, and it wasn't due to filenames or other specific large objects, it was due to the complexity of the game code.

If using stack makes your code simpler, and as long as you're testing properly, and as long as you don't go completely overboard (don't have multiple levels of file-handling functions which all put a filename on the stack), then I'd say just try it. Especially if the function would need to be able to fail anyway, whether you're using stack or heap. If it goes wrong, you either double the stack size and be more careful in future, or you add another failure case to your function. Neither is the end of the world.

Upvotes: 2

James
James

Reputation: 25513

If you're writing for a tiny little embedded platform, you worry about it all the time, but you also know exactly how big it is, and probably have some useful tools available to find the high-water mark of the stack.

If you aren't, then don't worry until your program crashes :) Unless you are allocating seriously huge objects (many tens of KB), then it is never going to be a problem.

Note, however, that objects on the stack are, by definition, temporary. Constructing (and possibly destructing) large objects frequently may cause you a performance problem - so if you have a large object it probably should be persistent and heap-based for reasons other than stack size.

Upvotes: 6

Thomas Matthews
Thomas Matthews

Reputation: 57678

I worry about stack size on embedded systems when call stack goes very deep and each function allocates variables (on the stack). Generally, panic evolves when the system crashes unexpectedly due to variables changing on the stack (the stack overflows).

Upvotes: 2

Richard Pennington
Richard Pennington

Reputation: 19965

In general, big allocations on the stack are bad for several reasons, not the least of which is that they can cause problems to remain well hidden for a long time.

The problem is that detecting stack overflow is not easy, and big allocations can subvert most of the commonly used methods.

If the processor has no memory management or memory protection unit, you have to be particularly careful. But event with some sort of MMU or MPU, the hardware can fail to detect a stack overflow. One common scheme, reserving a page below the stack to catch overflow, fails if the big stack object is bigger than a page. There just might be the stack of another thread sitting there and oops! you just created a very nasty, hard to find bug.

Unlimited recursion is usually easy to catch because the stack growth is usually small and will trigger the hardware protection.

Upvotes: 1

user224217
user224217

Reputation: 41

When deciding whether to allocate objects on the stack vs. the heap, there are also perf issues to be taken into consideration. Allocation of memory on the stack is very fast - it just involves moving the stack pointer, whereas dynamic allocation/deallocation using new/delete or malloc/free is fairly expensive, especially in multithreaded code that doesn't have a heap per thread. If you have a function that is being called in a tight loop, you might well err on the side of putting larger objects on the stack, keeping all of the multithreading caveats mentioned in other answers in mind, even if that means having to increase stack space, which most linkers will allow you to do.

Upvotes: 1

ChrisW
ChrisW

Reputation: 56083

When you are programming in a language that allows you to use automatic allocation for very large objects ...

If I want to allocate a very large object, then instead of on the stack I might allocate it on the heap but wrapped in an auto_ptr (in which case it will be deallocated when it goes out of scope, just like a stack-resident object, but without worrying about stack size).

... when and how do you worry about stack size?

I use the stack conservatively out of habit (e.g. any object bigger than about 512 bytes is allocated on the heap instead), and I know how big the stack is (e.g. about a megabyte by default), and therefore know that I don't need to worry about it.

Are there any rules of thumb for reasoning about stack size?

  • Very big objects can blow the stack
  • Very deep recursion can blow the stack
  • The default stack size might be too big (take too much total memory) if there are many threads and if you're running on a limited-memory embedded device, in which case you might want to use an O/S API or linker option to reduce the size of the stack per thread.

Upvotes: 14

Jason S
Jason S

Reputation: 189626

You care about it on a microcontroller, where you often have to specify stack space explicitly (or you get whatever's left over after RAM gets used for static allocation + any RAM program space).

Upvotes: 12

Yin Zhu
Yin Zhu

Reputation: 17119

my experience: when you use recursive functions, take care of the stack size!!

Upvotes: 3

xtofl
xtofl

Reputation: 41509

You start to worry about stack size when

  • someone on your team cunningly invents a recursive function that goes on and on and on...
  • you create a thread factory and suddenly need a tenfold of the stack that you used to need (each thread needs a stack => the more threads you have, the less free space remains for a given stack size)

Upvotes: 8

jldupont
jldupont

Reputation: 96716

Shouldn't you be avoiding using the stack for allocating large objects in the first place? Use the heap, no?

Upvotes: 3

Related Questions