3

Let me start by saying that I have read this tutorial and have read this question. My questions are:

  1. How big can the stack get ? Is it processor/architecture/compiler dependent ?

  2. Is there a way to know exactly how much memory is available to my function/class stack and how much is currently being used in order to avoid overflows ?

  3. Using modern compilers (say gcc 4.5) on a modern computer (say 6 GB ram), do I need to worry for stack overflows or is it a thing of the past ?

  4. Is the actual stack memory physically on RAM or on CPU cache(s) ?

  5. How much faster is stack memory access and read compared to heap access and read ? I realize that times are PC specific, so a ratio is enough.

  6. I've read that it is not advisable to allocate big vars/objects on the stack. How much is too big ? This question here is given an answer of 1MB for a thread in win32. How about a thread in Linux amd64 ?

I apologize if those questions have been asked and answered already, any link is welcome !

Community
  • 1
  • 1
Ælex
  • 14,432
  • 20
  • 88
  • 129
  • 4
    This would be better broken up into a few more focused questions, I think. – Jim Lewis Jul 01 '11 at 22:58
  • It's too broad to cover in a single answer, really, it's 10 entirely separate questions. – littleadv Jul 01 '11 at 23:04
  • how should I do that ? Take some questions out and ask them in another thread? – Ælex Jul 01 '11 at 23:04
  • If you ask the questions one by one, it is much easier for us to answer them. Otherwise you get "Yes, yes, yes, it depends, ...". – Bo Persson Jul 01 '11 at 23:08
  • @Alex: some compilers (eg: gcc 4.6) can compile C++ with the `-fsplit-stack` flag. This flag means that the stack will grow on demand. If you use it, then the stack overflow is effectively a thing of the past, as long as you have enough memory to begin with. – Matthieu M. Jul 02 '11 at 14:24

3 Answers3

8
  1. Yes, the limit on the stack size varies, but if you care you're probably doing something wrong.
  2. Generally no you can't get information about how much memory is available to your program. Even if you could obtain such information, it would usually be stale before you could use it.
  3. If you share access to data across threads, then yes you normally need to serialize access unless they're strictly read-only.
  4. You can pass the address of a stack-allocated object to another thread, in which case you (again) have to serialize unless the access is strictly read-only.
  5. You can certainly overflow the stack even on a modern machine with lots of memory. The stack is often limited to only a fairly small fraction of overall memory (e.g., 4 MB).
  6. The stack is allocated as system memory, but usually used enough that at least the top page or two will typically be in the cache at any given time.
  7. Being part of the stack vs. heap makes no direct difference to access speed -- the two typically reside in identical memory chips, and often even at different addresses in the same memory chip. The main difference is that the stack is normally contiguous and heavily used, do the top few pages will almost always be in the cache. Heap-based memory is typically fragmented, so there's a much greater chance of needing data that's not in the cache.
  8. Little has changed with respect to the maximum size of object you should allocate on the stack. Even if the stack can be larger, there's little reason to allocate huge objects there.
  9. The primary way to avoid memory leaks in C++ is RAII (AKA SBRM, Stack-based resource management).
  10. Smart pointers are a large subject in themselves, and Boost provides several kinds. In my experience, collections make a bigger difference, but the basic idea is largely the same either way: relieve the programmer of keeping track of every circumstance when a particular object can be used or should be freed.
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • I've got a last question for you, class member variables where are they by default allocated to ? (Assuming I do not specify them to be on the stack or heap). Thank you for answering my questions ! – Ælex Jul 01 '11 at 23:20
  • 1
    @Alex: static members are allocated (big surprise) statically. Otherwise, it depends on how you allocate the object, not how you define the class. – Jerry Coffin Jul 01 '11 at 23:22
  • 1
    @Alex members are stored wherever the object is stored. If you have `class Foo { Bar b; }` then putting a `Foo` on the stack will put a `Bar` on the stack. – Daniel Lubarov Jul 01 '11 at 23:29
  • Now there are 6 questions (not 10) so this answer doesn't make much sense any longer. Could you please (always) quote the question before asking it (if there are more than one question). – Serge Dundich Jul 02 '11 at 06:57
3

1.How big can the stack get ? Is it processor/architecture/compiler dependent ?

The size of the stack is limited by the amount of memory on the platform and the amount of memory allocated to the process by the operating system.

2.Is there a way to know exactly how much memory is available to my function/class stack and how much is currently being used in order to avoid overflows ?

There is no C or C++ facility for determining the amount of available memory. There may be platform specific functions for this. In general, most programs try to allocate memory, then come up with a solution for when the allocation fails.

3.Using modern compilers (say gcc 4.5) on a modern computer (say 6 GB ram), do I need to worry for stack overflows or is it a thing of the past ?

Stack Overflows can happen depending on the design of the program. Recursion is a good example of depleting the stack, regardless of the amount of memory.

4.Is the actual stack memory physically on RAM or on CPU cache(s) ?

Platform dependent. Some CPU's can load up their cache with local variables on the stack. Wide variety of scenarios on this topic. Not defined in the language specification.

5.How much faster is stack memory access and read compared to heap access and read ?
I realize that times are PC specific, so a ratio is enough.

Usuallly there is no difference in speed. Depends on how the platform organizes its memory (physically) and how the executable's memory is laid out. The heap or stack could reside in a serial access memory chip (a slow method) or even on a Flash memory chip. Not specified in the language specification.

6.I've read that it is not advisable to allocate big vars/objects on the stack. How much is too big ? This question here is given an answer of 1MB for a thread in win32. How about a thread in Linux amd64 ?

The best advice is to allocate local small variables as needed (a.k.a. via stack). Huge items are either allocted from dynamic memory (a.k.a. heap), or some kind of global (static local to function or local to translation unit or even global variable). If the size is known at compile time, use the global type allocation. Use dynamic memory when the size may change during run-time.

The stack also contains information about function addresses. This is one major reason to not allocate a lot of objects locally. Some compilers have smaller limits for stacks than for heap or global variables. The premise is that nested function calls require less memory than large data arrays or buffers.

Remember that when switching threads or tasks, the OS needs to save the state somewhere. The OS may have different rules for saving stack memory versus other types.

Jerska
  • 11,722
  • 4
  • 35
  • 54
Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
2

1-2 : On some embedded CPUs the stack may be limited to a few kbytes; on some machines it may expand to gigabytes. There's no platform-independent way to know how big the stack can get, in some measure because some platforms are capable of expanding the stack when they reach the limit; the success of such an operation cannot always be predicted in advance.

3 : The effects of nearly-simultaneous writes, or of writes in one thread that occur nearly simultaneously with reads in another, are largely unpredictable in the absence of locks, mutexes, or other such devices. Certain things can be assumed (for example, if one thread reads a heap-stored 'int' while another thread changes it from 4 to 5, the first thread may see 4 or it may see 5; on most platforms, it would be guaranteed not to see 27).

4 : Some platforms share stack address space among threads; others do not. Passing pointers to things on the stack is usually a bad idea, though, since the the foreign thread receiving the pointer will have no way of ensuring that the target is in scope and won't go out of scope.

5 : Generally one does not need to worry about stack space in any routine which is written to limit recursion to a reasonable level. One does, however, need to worry about the possibility of defective data structures causing infinite recursion, which would wipe out any stack no matter how large it might be. One should also be mindful of the possibility of nasty input which would cause a much greater stack depth than expected. For example, a compiler using a recursive-descent parser might choke if fed a file containing a billion repetitions of the sequence "1+(". Even if the machine has a gig of stack space, if each nested sub-expression uses 64 bytes of stack, the aforementioned three-gig file could kill it.

6 : Stack is stored generally in RAM and/or cache; the most-recently-accessed parts will generally be in cache, while the less-recently-accessed parts will be in main memory. The same is generally true of code, heap, and static storage areas as well.

7 : That is very system dependent; generally, "finding" something on the heap will take as much time as accessing a few things on the stack, but in many cases making multiple accesses to different parts of the same heap object can be as fast as accessing a stack object.

supercat
  • 77,689
  • 9
  • 166
  • 211