Board index » delphi » Stack overflow errors.

Stack overflow errors.

I keep getting stack overflow errors when I try to call a procedure which
outputs to the screen or printer. It's supposed to display the fields in a
record.

Any help would be much appreciated.(If you need more info, mail me.)

TIA

Owen.

... Science advances, funeral by funeral.
   -- Anon.
--
Gargamel : Arch-enemy of the bane of all humanity - The Smurfs. |
---------------------------------------------------------------'
garga...@argonet.co.uk /// For every PC out there, there's a Risc
                       /// waiting to be fulfilled.
Uploaded to news.dial.pipex.com at 20:16 on 29/10/1998

 

Re:Stack overflow errors.


   The best answer to your question can be given only when we get a
chance to view your code - please post the routine's source and the $M
directive with which you compile this program.
Quote
> I keep getting stack overflow errors when I try to call a procedure which
> outputs to the screen or printer. It's supposed to display the fields in a
> record.

> Any help would be much appreciated.(If you need more info, mail me.)

Re:Stack overflow errors.


In article <MPG.10a2ff41907e0b12989...@news.primenet.com>,

Quote
mrc...@primenet.com (Mike Copeland) wrote:

>    The best answer to your question can be given only when we get a
> chance to view your code - please post the routine's source

The code is below.

Quote
> and the $M directive with which you compile this program.

Pardon? I just use the TP7 compiler as is.

The error I get (Error 202 : Stack overflow error) comes about when I try to
display using the procedure DisplayData, but the cursor appears just below
the variable declaration of displayclients (*'d). Does TP not like having a
lot of fields in a record when you are accessing the record from a procedure
within a procedure? If I {} out a couple of fields all the way through, it
works fine, and it doesn't matter which ones I take out. "Device" is either
passed as "output" or "lst".

type
    textstring=packed array [1..stringsize] of char;
    code=packed array [1..3] of char;
    company=record
                  Name:textstring;
                  Contact:textstring;
                  Last_order:integer;
                  Date:integer;
                  Month:integer;
                  Year:integer;
                  ref_code:code;
            end;{company}
     directory=array [1..maxnum] of company;
     address=record
                   Contact:textstring;
                   Name:textstring;
                   line1:textstring;
                   line2:textstring;
                   line3:textstring;
                   line4:textstring;
                   line5:textstring;
                   postcode:textstring;
                   ref_code:code;
             end;{address}
     addbook=array [1..maxnum] of address;
var
   data:text;
   rolladex:directory;
   option:integer;
   size:integer;
   locations:addbook;

procedure outputclients(var device:text;a:company);
*****          begin
               with a do
               begin
                    write(device,'Company Name : ');
                    textout(device,name);
                    write(device,'Contact : ');
                    textout(device,contact);
                    write(device,'Size of last order : ');
                    writeln(device,last_order);
                    write(device,'Date of last order : ');
                    dateout(date,month,year,device);
                    write(device,'Reference Code : ');
                    writeln(device,ref_code);
               end;
               writeln(device);
          end;{outputclients}

procedure outputaddress(var device:text;b:address);
          begin
               writeln('Address :');
               with b do
               begin
                    textout(device,line1);
                    textout(device,line2);
                    textout(device,line3);
                    textout(device,line4);
                    textout(device,line5);
                    textout(device,postcode);
               end;
          end;{outputaddress}

procedure outputdata(dir:directory;abodes:addbook;size:integer;
                     var device:text);
          var
             index:integer;
             printing,display:boolean;
             show:char;
          begin
               write('Show addresses?');readln(show);
               if show in ['Y','y'] then display:=true
               else display:=false;
               if option=5 then printing:=TRUE
               else printing:=FALSE;
               for index:=1 to size do
               begin
                    outputclients(device,dir[index]);
                    if display then outputaddress(device,abodes[index]);
                    if not printing then repeat until keypressed;
               end;
               if printing then write(device,formfeed);
          end;

... Who said that?
--
Gargamel : Arch-enemy of the bane of all humanity - The Smurfs. |
---------------------------------------------------------------'
garga...@argonet.co.uk /// For every PC out there, there's a Risc
                       /// waiting to be fulfilled.
Uploaded to news.dial.pipex.com at 12:04 on 30/10/1998
Uploaded to news.dial.pipex.com at 12:35 on 30/10/1998

Re:Stack overflow errors.


Gargamel <garga...@argonet.co.uk> wrote in response to a request for
example code so that we might explain the reason for a program's
stack overflow.

[...snip...]

Quote
>... Does TP not like having a lot of fields in a record
>when you are accessing the record from a procedure within
>a procedure? If I {} out a couple of fields all the way
>through, it works fine, and it doesn't matter which ones
>I take out. "Device" is either passed as "output" or "lst".

[...snip program source...]

I know, all that work of including the code and I cut it from the
reply.  But, we've seen it and that is enough to identify your
problem.

The value of constants "StringSize" and "MaxNum" are pieces of
information you forgot to include.  Whatever their values, realize
that a company record contains two TextStrings and an address record
contains eleven TextStrings.  When you multiply their size by
MaxNum, you'll get a ball-park figure of the size of your data
structures.

Knowing how large your structures are, you only need to realize that
"value" parameters are copied to the stack to know that you are
trying to put a "lot" of data into a relatively small space.

Rather than pass large structures as "value" parameters, you need to
pass them as "reference" parameters (declare w/ VAR); or by passing
pointers to the structures; or by declaring them using the "const"
keyword.

If the procedure or function needs to modify the data, you would
normally pass the parameter by reference (as done w/ your device).
OTOH, when the procedure is not supposed to modify the data, you can
use the compiler to insure that it doesn't by declaring it as
constant data by using the "CONST" keyword.

Example:

PROCEDURE OutputData(CONST Dir: Directory;
                     CONST Abodes: Addbook;
                     Size: Integer; VAR Device: Text);

    ...red

Re:Stack overflow errors.


In article <363abb6c.1458...@news.leading.net>, rdon...@leading.net

Quote
(R.E.Donais) wrote:
> I know, all that work of including the code and I cut it from the
> reply.  But, we've seen it and that is enough to identify your
> problem.

Simple cut-and-paste job.

Quote
> The value of constants "StringSize" and "MaxNum" are pieces of
> information you forgot to include.  Whatever their values, realize
> that a company record contains two TextStrings and an address record
> contains eleven TextStrings.  When you multiply their size by
> MaxNum, you'll get a ball-park figure of the size of your data
> structures.

stringsize=30 and maxnum=99. Pretty big, huh?

[snip the rest]

It made sense the third time round :)

That's fixed now, but a new problem has arisen - I wrote a function to tell
me whether or not a file existed before trying to write/load to/from it, but
for some unknown reason, I get an "Error 88 - '(' exepected at in the
function (*'d)

function filexist(name:string):boolean;
  var
     results : searchrec;
  begin

    filexist := false;
    FindFirst (name, AnyFile, results);
    if DosError = 0 then
      if (results.attr <> Directory)* and (results.attr <> VolumeId) then
        filexist := true;
  end;{filexist}

Any ideas?

Are you calling me ISP-ist? Some of my best friends are AOLers!
--
Gargamel : Arch-enemy of the bane of all humanity - The Smurfs. |
---------------------------------------------------------------'
garga...@argonet.co.uk /// For every PC out there, there's a Risc
                       /// waiting to be fulfilled.
Uploaded to news.dial.pipex.com at 21:54 on 30/10/1998

Re:Stack overflow errors.


Quote
>    if DosError = 0 then
>      if (results.attr <> Directory)* and (results.attr <> VolumeId) then
>        filexist := true;                  |||||||

What is this star symbol doing after the parenthesis?

Nik.

Re:Stack overflow errors.


Quote
Gargamel <garga...@argonet.co.uk> wrote:
>It made sense the third time round :)
>That's fixed now, but a new problem has arisen - I wrote a function to tell
>me whether or not a file existed before trying to write/load to/from it, but
>for some unknown reason, I get an "Error 88 - '(' exepected at in the
>function (*'d)

>function filexist(name:string):boolean;
>  var
>     results : searchrec;
>  begin

>    filexist := false;
>    FindFirst (name, AnyFile, results);
>    if DosError = 0 then
>      if (results.attr <> Directory)* and (results.attr <> VolumeId) then
>        filexist := true;
>  end;{filexist}

>Any ideas?

I believe you'll find that your code has declared a function named
"Directory".  Since this new declaration occurs after the USES
clause, it becomes the default association for "Directory".  You can
either rename your directory function so that there is no name
conflict, or qualify the offending statement.  You're bound to have
conflicts with complex programs or when using objects so you may as
well start using qualifiers.  

A qualifier uses the unit name and period just like a reference to a
record or object.  Makes sense if you consider a unit as a single
instance object.  Don't get hung up on the reference to objects.
You don't have to understand it at this point, simply use the
following example ---

if (results.attr <> DOS.Directory) ... then
                    ^^^^ qualifies Directory to be _the_ Directory
that is defined in the DOS unit!

BTW, boolean expressions have a boolean result so you could reduce
your function to ---

function filexist(name:string):boolean;
var results : searchrec;
begin
   FindFirst (name, AnyFile, results);
   filexist := (DosError = 0)
           and (results.attr <> DOS.Directory)
           and (results.attr <> VolumeId);
end;{filexist}

    ...red

Re:Stack overflow errors.


In article <6it_1.663$_3.6253...@news.magma.ca>, "Nik Synytskyy"

Quote
<nik...@NOSPAMmondenet.com> wrote:

> >    if DosError = 0 then
> >      if (results.attr <> Directory)* and (results.attr <> VolumeId) then
> >        filexist := true;                  |||||||

> What is this star symbol doing after the parenthesis?

It indicates where the cursor appears when the compiler stops and displays
the error message.

--
Gargamel : Arch-enemy of the bane of all humanity - The Smurfs. |
---------------------------------------------------------------'
garga...@argonet.co.uk /// For every PC out there, there's a Risc
                       /// waiting to be fulfilled.

Re:Stack overflow errors.


JRS:  In article <na.014e2d489d.a500d0garga...@argonet.co.uk> of Fri, 30
Oct 1998 20:25:15 in comp.lang.pascal.borland, Gargamel

Quote
<garga...@argonet.co.uk> wrote:
>That's fixed now, but a new problem has arisen - I wrote a function to tell
>me whether or not a file existed before trying to write/load to/from it, but
>for some unknown reason, I get an "Error 88 - '(' exepected at in the
>function (*'d)

>function filexist(name:string):boolean;
>  var
>     results : searchrec;
>  begin

>    filexist := false;
>    FindFirst (name, AnyFile, results);
>    if DosError = 0 then
>      if (results.attr <> Directory)* and (results.attr <> VolumeId) then
>        filexist := true;
>  end;{filexist}

In the code you posted earlier, you have used Directory as a var.  Try
using System.Directory here.  The following are untested, but indicate
how your Pascal can be shortened.

FindFirst (name, AnyFile, results);
with results do filexist := (DosError = 0) and
  (attr <> System.Directory) and (attr <> VolumeId) ;

FindFirst (name, AnyFile, results);
with results, System do (* not sure about with on a Unit! *)
  filexist := (DosError = 0) and (attr and (Directory or VolumeID)=0) ;

--
John Stockton, Surrey, UK.    j...@merlyn.demon.co.uk    Turnpike v4.00    MIME.
  Web <URL: http://www.merlyn.demon.co.uk/> - TP/BP/&c. FAQqish topics & links.
  Timo's TurboPascal <A HREF="ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip">FAQ</A>.
  <A HREF="http://www.merlyn.demon.co.uk/clpb-faq.txt">Mini-FAQ</A> of c.l.p.b.

Re:Stack overflow errors.


In article <363b1392.943...@news.leading.net>, rdon...@leading.net

Quote
(R.E.Donais) wrote:

> I believe you'll find that your code has declared a function named
> "Directory".

It's actually a variable type (An array that holds addresses).

Quote
> Since this new declaration occurs after the USES
> clause, it becomes the default association for "Directory".  You can
> either rename your directory function so that there is no name
> conflict,

That would mean changing a /lot/ of code so ...

Quote
> or qualify the offending statement.  You're bound to have
> conflicts with complex programs or when using objects so you may as
> well start using qualifiers.  

... this seems the better method.

Quote
> BTW, boolean expressions have a boolean result so you could reduce
> your function to ---

Cheers.

Owen

--
Gargamel : Arch-enemy of the bane of all humanity - The Smurfs. |
---------------------------------------------------------------'
garga...@argonet.co.uk /// For every PC out there, there's a Risc
                       /// waiting to be fulfilled.

Re:Stack overflow errors.


Another problem with stack overflows -

I wrote a backup procedure which loads information from a file into a new
array of records, and then saves them to a different file. The only problem
is I get a stack overflow error when I declare the new arrays. It's for the
same reason as before, but I don't see how I can get around it this time,
because the new arrays must be variable to load the information into them.
After that, they can become constant, but they must be variable for the
loading to take place.

I hope there is a way around this problem, as I do not wish to have to use
an algorithm which simply copies the file.

TIA.

--
Gargamel : Arch-enemy of the bane of all humanity - The Smurfs. |
---------------------------------------------------------------'
garga...@argonet.co.uk /// For every PC out there, there's a Risc
                       /// waiting to be fulfilled.

Re:Stack overflow errors.


In article <na.5135c7489e.a500d0sb...@argonet.co.uk>,

Quote
Gargamel  <sb...@argonet.co.uk> wrote:
>Another problem with stack overflows -

>I wrote a backup procedure which loads information from a file into a new
>array of records, and then saves them to a different file. The only problem
>is I get a stack overflow error when I declare the new arrays. It's for the
>same reason as before, but I don't see how I can get around it this time,
>because the new arrays must be variable to load the information into them.
>After that, they can become constant, but they must be variable for the
>loading to take place.

Code????

Variable parameters are no problem for the stack use. A variable
parameter always takes only 4 bytes from the stack. It is the value
parameters that are the problem but on new versions of TP 7.0 there is no
need to use them unless one wants to use them as temporary variables
(which IMO is ugly)

Osmo

Other Threads