FB II Compiler

PG PRO

Debugging

Memory

System

Mathematics

Resources

Disk I/O

Windows

Controls

Menus

Mouse

Keyboard

Text

Fonts

Drawing

Sound

Clipboard

Printing

Communication

ASM

Made with FB

MEMORY

Calculate the Stack space


Local variables, including arrays, are allocated on the stack, which is generally _much_ smaller than the heap. A very large local array will cause the stack to collide with the heap, with a crash.
How much stack space can you safely use? The space available turns out to depend on the compiled application's Get Info memory allocation.
_max=31
LOCAL FN Test&
 DIM s$(_max) 'allocate (_max+1)*256 bytes + 12 bytes for a LOCAL FN
END FN=FN STACKSPACE

WINDOW 1
before& = FN STACKSPACE
during& = FN Test&
after&  = FN STACKSPACE
PRINT before& "before"
PRINT during& "during"
PRINT after& "after"
PRINT "Used by FN Test&=" before&-during&
DO
UNTIL FN BUTTON
Investigation with a compiled app from the above program, and various memory allocations (in the OS 8.5 Get Info window) shows that FB2 sets the "before" stack as:-
    initial_stack_size = min (32440, 1400 + 32*Kpartition)

where Kpartition is the number of K entered.
For example with 8000K the stack is a huge 257400 bytes. With 100K the stack is only 32440 bytes, and a crash should be expected if _max > = 126.
With a global DIM, the memory is taken from the application's heap.
Robert

I ran your program. Thanks.
I changed _max to 5000 and s$ to 100 chars. I ran it uncompiled in FBII with 18000K allocated. When I ran the modified code, during& went negative.
As I decrease the size of _max, during& approaches zero then goes positive.
What does that mean?
_max=5000
LOCAL FN Test&
 DIM 100 s$ (_max)
END FN=FN STACKSPACE

 WINDOW 1
 before& = FN STACKSPACE
 during& = FN Test&
 after&  = FN STACKSPACE
 PRINT before& "before"
 PRINT during& "during"
 PRINT after& "after"
 PRINT "Used by FN Test&=" before&-during&
 DO
 UNTIL FN BUTTON
Pierre A. Zippi

When FN STACKSPACE is negative it means that you
(a) have attempted to use more stack than the system has reserved, and
(b) are a hair's-breadth away from a crash.
The only reason that your program didn't crash was that the array (illegally spilling over the top of the stack) was never accessed in FN Test&. The modified FN Test& below shows how to crash into BowelsOfTheMemoryManager.
Conclusion: don't use the stack for a large array. Either globally DIM it, or use relocatable memory (FN NEWPTR and XREF, or FN NEWHANDLE and XREF@).
_max=5000
LOCAL FN Test&
 DIM 100 s$ (_max)
 LONG IF FN STACKSPACE<100
  INPUT "OK to crash?"; ok$
  IF UCASE$(ok$)<>"Y" THEN END
 END IF
 FOR j=0 TO _max
  s$(j)=""
 NEXT
END FN=FN STACKSPACE

WINDOW 1
before& = FN STACKSPACE
during& = FN Test&
PRINT before& "before"
PRINT during& "during"
PRINT "Used by FN Test&=" before&-during&
DO: UNTIL FN BUTTON
Robert

>> Conclusion: don't use the stack for a large array. Either globally DIM it, or <<

Now, would someone like to go out on a limb and say _how large_ is large? Is there some absolute number, or a proportion of total application size, or a proportion of the memory you've typically got available or something else entirely? I've only got one situation where I rely on local arrays in a big way, and have never had problems with it. But if there's a danger of collision (stacks? heaps? why can't I use scaffolding and re-bars?) I'd like to be sure I'm staying within the safety zone.

Lucy

(1) This is "Black Art" stuff, but (3) and (4) below help.

(2) Every time a FN is called, its stack allocation is used. The allocation is released at the END FN statement.

(3) The total stack space is not documented in the FB manuals, but by experiment is:-

> initial_stack_size = min (32440, 1400 + 32*Kpartition)
> where Kpartition is the number of K entered

So in the main program of a compiled application you have at least 32K of stack. If the application's Get Info memory is greater than about 1000K, you'll have more.

(4) If stack overflow is a real worry, you can do a check within a FN, before allowing it to call another FN (or itself, as in this example)
LOCAL FN Recursion(depth)
 _myArrayBytes=1024     ' for DIM localStuff%(511)
 _myOtherVarBytes=100   ' guess (over-generous in this case)
 _safetyBytes@00      ' guess
 _stackBytesNeededForFN=_myArrayBytes_myOtherVarBytes_safetyBytes
 DIM localStuff%(511)  'use 1024 bytes of stack
 PRINT "Depth=" depth ; " Stack available=" FN STACKSPACE
 LONG IF FN STACKSPACE>_stackBytesNeededForFN 'ok for recursive call?
  FN Recursion(depth+1)
 XELSE
  PRINT "Maximum depth =" depth
 END IF
END FN

WINDOW 1
FN Recursion(0)
DO: UNTIL FN BUTTON
As an illustration of Black Art aspect, in the FB environment I get a crash if _safetyBytes is less than about 4000, but in a compiled app _safetyBytes=1000 works OK.

(5) None of this messy stuff is necessary, unless you're allocating substantial chunks of LOCAL variable/array memory, or you're using deep recursion.
Robert