phils@tekigm2.TEK.COM (Philip E Staub) (11/12/88)
First of all, I'd like to thank all those who took the time to reply to my stack size survey request. I received about 20 replies, many of them with some well thought out and appreciated comments. Somewhat as I had expected, the answers varied all over the map. Several people were happy with the 4K default stack size, but for purposes of programming, most preferred a stack anywhere from 10K to 32K. And one even went up to 60K. (After all, memory is cheap, right? 8-( ). Also, not surprisingly, most people indicated that they set up some particular stack size and use it for all purposes. This means they usually set it to the largest size they feel they will ever need, and use that size even for things which require far less than the default. For purposes of trying to categorize the summary which follows, I'll divide it into three sections. The first will be the stack size which people use for most "everyday" applications, such as editors, terminal emulators, background processes such as dmouse, shells, etc. The second group consists of programming environments. For people who didn't explicitly identify the size they use for these two categories, I assumed they use the same size for both. The third group consists of some comments about specific programs. For the first two categories, I count one "vote" for each answer. Also, I've rounded the sizes to the nearest 'K', so that an answer of either 4000 or 4096 will be reported as 4K. Final Vote Tally: Size(K) Applications Programming 4 4 2 8 1 2 10 2 2 11 1 1 16 2 2 20 1 2 25 2 2 30 3 3 32 1 1 60 1 1 Comments about specific programs (K): Lattice C 10 Manx C 8 TDI Modula-2 30 Absoft FORTRAN linker up to 50 Maple 256(!) nethack 25 dbw_render up to 50 uudecode 16 shar 16 AmigaTeX 10 QRT2 10 Some general comments: There are two basic ways to monitor stack utilization. First, both of the major compilers have options for compilation which allow run-time stack checking at the expense of slightly larger program size and slightly slower program execution. Second, is to initialize the entire stack to some known character before program execution begins and check to see how many bytes of the stack were overwritten when the program exits. The first method works if you have the source available or if the author has compiled the program with stack checking enabled. The second method conceivably would not have these restrictions, because it implies the availability of a stack monitor program which runs the program under test unmodified, and handles the initialization of the stack before and the checking of the stack after running the program. However, the results may not be reliable, because merely allocating an automatic array on the stack does not guarantee that any given element of that array will ever be touched by the routine which allocates it (or any other routine which that routine calls). Consider the following example. Upon entry to a particular routine, we have 4000 bytes of stack left. This routine (we'll call it 'foo') has 3 automatic variables allocated: 'i' a long integer, 'j' an array of 2000 long integers, and 'k' another long integer, declared in that order. Upon entry to the routine, stack space is allocated at offsets of -4, -8004, and -8008 bytes from the frame pointer for 'i', 'j', and 'k' respectively. Now lets say we write a value into 'k'. Notice that since we only have 4000 bytes left on the stack, the bottom of the area which we are authorized to touch ends at an offset of -4000 bytes from the frame pointer. Access to 'k' is almost certainly in an address range which does not belong to this process, and it is definitely not in the range allocated for its stack. If we're lucky, we won't hit anything important when we change it, and the user will never know the difference, at least until we try to run 'foo' in a slightly different environment in which the access to 'k' creates such havoc as destroying the memory free list, or corruption of the stack or even alteration of the code of another running process. Talk about your basic impossible to track down bug. Also, consider the case in which no element of 'j' is changed. In this case the stack monitor program would never notice that the limits of the stack had been violated, because there would be no way to tell it to check beyond the bottom of the stack for values which may have been illegally changed, as in the case of modifying 'k'. All this points to the fact that in a non-memory protected, multitasking envioronment like the Amiga, stack overflow bugs can be some of the most insidious to try to track down. Consider this as a plea for any automatic variable larger than 100 bytes or so to be 'malloc()'ed' (or AllocMem()'ed), rather than allocated on the stack. Oh, yes. I almost forgot. I promised to let you know how things worked out for me at 25K instead of 10K. The answer... things are much more stable. Sorry if this seemed to ramble on, but hopefully some of it will be enlightening to someone. Happy hacking, Phil -- ------------------------------------------------------------------------------ Phil Staub Tektronix, Inc., Vancouver, Washington 98668 phils@tekigm2.MEN.TEK.COM