Board index » delphi » Stack overflow erros..

Stack overflow erros..

        Hopefully someone can help me.. out there.. I have created a DLL
which reads in a cutomer binary file. So far i have been able to read and process
200 customers.. however, when i try to increase the number of customers to
250 then I get a stack overflow error. I have looked the dataytpe and the
number of bytes it would take up and still i dont se how I could get a stack
overflow. The question.. is then.. how i do solve this problem.. rather
what are the possible situations when i would get a stack overflow??
and  is there any way i can get around it..??

-kxm

 

Re:Stack overflow erros..


Quote
Kamlish Misra (mis...@pitt.edu) wrote:
>    Hopefully someone can help me.. out there.. I have created a DLL
> which reads in a cutomer binary file. So far i have been able to read and
> process 200 customers.. however, when i try to increase the number of
> customers to 250 then I get a stack overflow error. I have looked the
> datatype and the number of bytes it would take up and still i dont se how
> I could get a stack overflow. The question.. is then.. how i do solve this
> problem.. rather what are the possible situations when i would get a stack
> overflow?? and is there any way i can get around it..??

Don't you have a procedure calling itself recursively ?

If you're using something like :

Type  CustArray = Array[1..250] of Customers;

and then

Procedure DisplayCust(c:CustArray);
Begin
End;

your CustArray is too big to fit in the allocated stack.

Depending on the problem, you can stop a procedure from calling itself. In
the second case, a quick and dirty fix would be to add "Var" in you
procedure declaration :

Procedure DisplayCust(Var c:CustArray);
Begin
End;

In the latter case, don't modify "c" since it would modify the original
variable.

The correct way would be to restructure the program/variables so that it/they
could work with any number of customers.

Also check your {$M xxx,yyy,zzz} defines (xxx in this case). Type ^O^O to
make it appear at the top of your source code. Maybe you could allocate a
little more stack to your program (increase xxx).

Good luck !

--
Jean-Christophe Boggio                          c...@gestalt.freenix.fr
Pascal and Linux {*word*60}, Dos and Windows independent programmer.

Re:Stack overflow erros..


In article <3veajh$...@usenet.srv.cis.pitt.edu>,

Quote
Kamlish Misra <mis...@pitt.edu> wrote:
>    Hopefully someone can help me.. out there.. I have created a DLL
>which reads in a cutomer binary file. So far i have been able to read and process
>200 customers.. however, when i try to increase the number of customers to
>250 then I get a stack overflow error. I have looked the dataytpe and the
>number of bytes it would take up and still i dont se how I could get a stack
>overflow. The question.. is then.. how i do solve this problem.. rather
>what are the possible situations when i would get a stack overflow??
>and  is there any way i can get around it..??

You can get a stack overflow in one of two ways:  You allocate too many local
variables, or you have a recursive function that calls itself too often.
Overflowing on going from 200 to 250 customers could be caused by either
scenario.  However, since I rather doubt that you have a routine that
if not EOF process one record and calls itself, it's most likely that somewhere
you have allocated an array of N customer records.  (If you don't see how this
is blowing up the stack, maybe you have two or three copies.)  The solution
is to either move this big array to the heap or to not try to read the whole
file into memory, but work on only N records at a time, where N may be 1 or 200
....
--

http://www.armory.com/~jon                       Personal and Technical Pages
http://www.armory.com/~jon/hs/HomeSchool.html Home School Resource Pages

Re:Stack overflow erros..


Quote
In article <3veajh$...@usenet.srv.cis.pitt.edu> mis...@pitt.edu (Kamlish Misra) writes:
>From: mis...@pitt.edu (Kamlish Misra)
>Subject: Stack overflow erros..
>Date: 29 Jul 1995 21:52:49 GMT
>        Hopefully someone can help me.. out there.. I have created a DLL
>which reads in a cutomer binary file. So far i have been able to read and process
>200 customers.. however, when i try to increase the number of customers to
>250 then I get a stack overflow error. I have looked the dataytpe and the
>number of bytes it would take up and still i dont se how I could get a stack
>overflow. The question.. is then.. how i do solve this problem.. rather
>what are the possible situations when i would get a stack overflow??
>and  is there any way i can get around it..??
>-kxm

Usually this is caused by a loop that has a problem and eats up stack space.  
Since the stack is a finite quantity, my guess is that the 200 entries aren't
enough to use it all up, but 250 is.  You might try increasing your stack size
to see if the symptom goes away.  If it does, don't stop there.....try to find
out what is eating it up.  Are you, for example, calling procedures
recursively (calling a loop from within the loop) or allocating variables
without releasing them, etc.  My guess is you will find something along those
lines.

-Dave

Re:Stack overflow erros..


Hi Dave!

k> Since the stack is a finite quantity, [...]
Yes, especially the way Borland uses it since at least version 5.0.

For example, take this following stupid code:

var
  i: integer;
  s: string;
begin
  if copy(s,1,1)=' ' then
    i:=1
  else if copy(s,1,1)=' ' then
    i:=2
  else if copy(s,1,1)=' ' then
    i:=3;
  end.

Commented unassembly:
                                        ; begin
0002 CALL   system.init
0007 ENTER  0300,00             ; Space for 3 strings (!)
                                        ;   if copy(s,1,1)=' ' then
000B LEA    DI,[BP+FF00]        ; first temp string (bp-$100)
000F PUSH   SS
0010 PUSH   DI
0011 MOV    DI,offset s
0014 PUSH   DS
0015 PUSH   DI
0016 PUSH   01
0018 PUSH   01
001A CALL   system.copy
001F MOV    DI,0000             ; @ ''
0022 PUSH   CS
0023 PUSH   DI
0024 CALL   system.compare_str
0029 JNZ    0033
                                        ;     i:=1
002B MOV    Word Ptr [i],0001
0031 JMP    0081
                                        ;   else if copy(s,1,1)=' ' then
0033 LEA    DI,[BP+FE00]        ; second temp string (bp-$200)
0037 PUSH   SS
0038 PUSH   DI
0039 MOV    DI,offset s
003C PUSH   DS
003D PUSH   DI
003E PUSH   01
0040 PUSH   01
0042 CALL   system.copy
0047 MOV    DI,0000
004A PUSH   CS
004B PUSH   DI
004C CALL   system.compare_str
0051 JNZ    005B
                                        ;     i:=2
0053 MOV    Word Ptr [i],0002
0059 JMP    0081
                                        ;   else if copy(s,1,1)=' ' then
005B LEA    DI,[BP+FD00]        ; third temp string (bp-$300)
005F PUSH   SS
0060 PUSH   DI
0061 MOV    DI,offset s
0064 PUSH   DS
0065 PUSH   DI
0066 PUSH   01
0068 PUSH   01
006A CALL   system.copy
006F MOV    DI,0000
0072 PUSH   CS
0073 PUSH   DI
0074 CALL   system.compare_str
0079 JNZ    0081
                                        ;     i:=3;
007B MOV    Word Ptr [i],0003
                                        ;   end.
0081 LEAVE
0082 XOR    AX,AX
0084 CALL   system.halt

Now the crucial question:
  Why is space for THREE strings allocated? One should be enough!

BTW: Nearly all compiler I know of have this kind of quirk, e.g.
  - Borland Pascal (5, 5.5, 6, 7, Delphi)
  - Virtual Pascal
  - Microsoft C
  - IBM C set
  - Gnu C++

Well, I found a quick and really dirty solution to get around this problem:
Let's cut the stack off below all variables you use!
Don't use this when you do not know *exactly* what you are doing!

The routine cut_stack removes the stack space up to the parameter variable.
The parameter variable is the last one you use during and after the call.
Restore the stack with restore_stack.

Typically place the cut_stack/restore_stack immediately surround the recursive
call. There must be *no* expression which uses temporary variables in the
current stack frame (e.g. string functions (copy, concat, etc.)).
Don't use it within FOR, WITH, or exception handling statement!
In case of question, please consult your de{*word*81}!

procedure cut_stack(var rec);
inline(
   $58          (* pop   ax      -- rec.ofs       *)
  /$5a          (* pop   dx      -- rec.seg (=ss) *)
  /$94          (* xchg  ax,sp   *)
  /$50          (* push  ax      *)
  );
procedure restore_stack;
inline(
   $58          (* pop   ax      *)
  /$94          (* xchg  ax,sp   *)
  );

Example:

program stacktest;
(*$s+*)  (* stack check on *)

...here comes the declaration of cut_stack/restore_stack (or uses statement)

var
  i: integer;
function test:integer;
var
  (* Variables which should be saved across the call *)
  a: integer;
  (* --- *)
  dummy: record end;
  (* Variables which may be destroyed during the call *)
  s: string;
begin
  (* Eating up 8 Strings (2KB)... *)
  s:='x';
  s:=copy(copy(copy(copy(copy(copy(copy(copy(s
     ,1,1),1,1),1,1),1,1),1,1),1,1),1,1),1,1);
  inc(i);
  if i<100 then begin
    cut_stack(dummy);
    a:=test;                                   (* <- Call *)
    restore_stack;
    end
  else a:=1;
  test:=a+1;
end;

begin
  i:=0;
  write(test);
  end.

Try this without the stack truncation (comment out both lines)...

Greetinx Jane
PS: I reported this to Borland 1991 and no sensible reaction occurred.  :-(

Other Threads