?
Solved

BIG Memory Problems....

Posted on 2003-03-28
14
Medium Priority
?
215 Views
Last Modified: 2010-04-16
Helo,
im writing a simple raycasting engine, ive set up some memory in the program for a virtual screen which i flip to vga. it is all working fine, but after about a minute the program stops with error 200: stack overflow, i cant see why it would do this, as i am reusing most variable and reusing the memory for the screen by looping the program.
any ideas or solutions anyone?
thanks - DF
0
Comment
Question by:nislick
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 2
  • +3
14 Comments
 
LVL 3

Expert Comment

by:lmikle
ID: 8227688
Check your code on a deep recursion.
If your program call any recursive procedure that on each step allocate a lot of memory (even if it is a local variables) on one of recursive call the heap will ending. and you got a Stack overflow error.

If you find procedure with deep recursion you have a 2 ways to solve your problem.

1st - replace recursion by loop.
2nd - allocate memory in a global heap.

Also chack that you release allocated memory in each call of recursive procedure.

For more detailed analisys please post you code here.
0
 
LVL 22

Expert Comment

by:grg99
ID: 8227846
Try printing out Memavail every time thru the main loop.
You may have a memory leak.

Also in raycasting it's not unusual to recur a whole lot.  Imagine two surfaces that are almost parallel.  You could really go very deep into recursion.

I would keep a recursion level count.  If it recurs more than N times (N = 5 to 10 is about right) then just ignore that point and return.  There's not much detail you're going to gain by recursing that much.


Regards,


grg99
0
 

Author Comment

by:nislick
ID: 8227927
ive provided most of my code here - i left out some bits where its just calculations, not recursion, tho there is some looping in creating the tables, using the same variable.
ive jsut started using mem procedures, im not sure how to set it globaly, or how to release it properly....
cheers heres the code;;; quite a bundle of mess, sorry bout that, have 2 tidy it up!

uses crt,gfx,cossin;
type    virtualvga = array[1..64000] of byte;  ** memory stuff**
        virtptr    = ^virtualvga;

const   ang_0=0;     ang_30=160;   ang_45=240;   ang_90=480;
        ang_180=960; ang_270=1440; ang_360=1920; ang_195=1040;
        incangle=0.1875;
        maxdistance=1000;
        horizon=100;       **middle of screen, centre view**
        grid: array[1..4,1..4] of byte=  **map - sorta**
        ((0,0,0,0)
         (0,0,0,0)
         (0,0,0,0)
         (0,0,0,0));

var     ystep,xstep:array[0..1920]of real;  ** for calctables**
        scaletable: array[0..319] of real;
        htable:array[0..9790]of integer;
       
        yrad,xrad: integer;   **distances for x+y rays**
        loop1,x,xpos,ypos,playerx,playery,angle,shortdist:integer;  ** general global variables**
        key:char;
        checkhit:boolean;

        virtscr:  virtptr;  ** memory stuff**
        vaddr: word;


procedure setmemory;   ** starts memory**
begin
     getmem(virtscr,64000);
     vaddr:= seg (virtscr^);
end;

procedure calctables;   **calculates tables for use in addin lengths + getting height for screen**

procedure check(x,y:real; ray:char);             **check if rays hit walls**
begin
     checkhit:=false;
If ray='x' then
   if (angle=ang_90)or(angle=ang_270) then checkhit:=true else
   if (x<=0)or(x>=576) then checkhit:=true;
   if (grid[round(x/64),round(y/64)])>0 then checkhit:=true;
** same for yray**
end;


function dist(x,y:real; ray:integer):integer; **find distance of ray to wall**

procedure putpixel(x,y:integer; colour:byte; where:word);   **draws to virtual screen**
begin
     mem[where:x+(y*320)]:=colour;
end;

procedure flip;                       **flips from virtual to vga screen**
begin
waitretrace;
     move(virtscr^,mem[vga:0],64000);
cls(vaddr,0);
end;

procedure drawscreen(x,h:integer);            **finds where to draw from and draws to virtaul screen*
var ty,by:integer;
begin
** find top of line and bottom of line then subtract each**
repeat
     putpixel(x,ty,72,vaddr);
     inc(ty);
until ty>=by; **repeats pixel after pixel until top reaches bottom** - is there another way around this?
end;


procedure xray;                  ** xray ends when hits wall**
var ynext:real;
    xposxray,yposxray:real;
begin
xposxray:=playerx;
yposxray:=playery;
ynext:=ystep[angle];
repeat

**adds/subtracts from xray length depending on angle and position**

check(xposxray,yposxray,'x');
until (checkhit=true);
     xrad:=dist(xposxray,yposxray,x);
end;


procedure yray;                  ** same as xray**
var xnext:real;
    xposyray,yposyray:real;
begin
xposyray:=playerx;
yposyray:=playery;
xnext:=xstep[angle];
repeat

**Adds/subtracts from yray length depending on angle and position**

check(xposyray,yposyray,'y');
until (checkhit=true);
     yrad:=dist(xposyray,yposyray,x);
end;

procedure calcview;            ****MAIN PROGRAM - 'REPEAT' IS MAIN LOOP, THEN AT END THERE IS RECURSION...***
var dx,dy:integer;
begin
angle:=angle-x;

if keypressed=true then key:=readkey;
case key of
     'q': exit;
     'd': begin cls(vga,0); angle:=angle+240; flag:=false; end;
end;

key:=#0;
x:=0;

repeat
if angle>ang_360 then angle:=angle-ang_360 else
if angle<ang_0 then angle:=angle+ang_360 else angle:=angle;
xray;
yray;

if xrad<yrad then shortdist:=xrad else
   if yrad<xrad then shortdist:=yrad else
      if xrad=yrad then shortdist:=xrad;

drawscreen(x,htable[shortdist]);

inc(x);
inc(angle);
if keypressed=true then key:=readkey;

until (x>=320)or(key='q')or(key='d')or(key='a')or(key='w')or(key='s')or(keypressed=true);

flip;

if key<>'q' then calcview;
end;

procedure freememory;                  **frees memory**
begin
     freemem(virtscr,64000);
end;

begin                  ** start of program**
clrscr;
x:=0;
playerx:=192;
playery:=384;
            calctables;
            setmemory;
angle:=ang_360;
            setmcga;
            calcview;
            settext;
            freememory;
end.
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
LVL 15

Expert Comment

by:VGR
ID: 8228235
as previously pointed out partially, stack overflow occurs when local variables are too big. This includes recursion when allocating local variables. I don't see anything like this in the code above (you use globals).

I think the problem is in DrawScreen, althought I can't prove it.

Have you tried going step by step while surveying MemTotal and MemAVail (if I remember well) - I know this is for the Heap, but anyway you can't really look at the stack unless you go down to the registers level in CPU window mode and quasi-debug your program.

You could pass it to Purify

Sorry to be of no help.

Well, actually, I may be os some help :D

This procedure should be rewritten :
procedure check(x,y:real; ray:char);             **check if rays hit walls**
begin
  {$B+}
    checkhit:=false;
If ray='x' then
  checkhit:=(angle=ang_90)or(angle=ang_270)
else checkhit:=(x<=0)or(x>=576);
  checkhit:=checkhit OR grid[round(x/64),round(y/64)]>0;
** same for yray**
  {$B-}
end;

0
 
LVL 15

Expert Comment

by:VGR
ID: 8228244
and excuse-me, but those types :
type    virtualvga = array[1..64000] of byte;  ** memory stuff**
       virtptr    = ^virtualvga;

don't seem to be used :/

I won't complain, because one single instance of this virtualvga thing would occupy the full DATA segment 8-)
(65520 if my memory is correct)

If ever you can't trace the problem, I suggest changing the data model towards the Heap, paying very good attention to New/Dispose pairs and logic.
0
 

Author Comment

by:nislick
ID: 8228687
please do...criticism is a good thing :), but those type values are used by - virtscr:  virtptr;  ** memory stuff**
       vaddr: word;
0
 

Author Comment

by:nislick
ID: 8228715
the virtscr variable points to the array and so doesnt use up the 64k allowed but uses 640k base memory.
any ideas on how to change the data model towards the heap, because i have no idea :¬|
0
 
LVL 15

Expert Comment

by:VGR
ID: 8229626
for instance :
in stead of :
type    virtualvga = array[1..64000] of byte;  ** memory stuff**
      virtptr    = ^virtualvga;
Var somevar : virtualvga; // 64000 bytes from DATA

you may do

Var somevar : virtptr;

begin
  // stuff
  somevar:=New(virtptr);
  // stuff
  Dispose(somevar);
end.


so in fact, that's what you're using already 8-)
0
 
LVL 49

Expert Comment

by:dbrunton
ID: 8230067
Try using the Turbo Pascal compiler directives as well.

In this case it should be

{$M stacksize, heapmin,heapmax}

stacksize is in range 1024 to 65520.  By default the stacksize is 16K but change it to 65520.  This will give you heaps of stack for recursion purposes.

I'd recommend you try

program whatever;
{$M 65520,0,655360}
uses crt,gfx,cossin;

and see how it runs.  (May want to change that heapmax down a little)

0
 
LVL 1

Accepted Solution

by:
Okey earned 150 total points
ID: 8248188
Ever thought about that Parameters and variables are allways transferred to stack and that every string-constant is passed in TP over Stack?
Pascal uses to address its Data for routines trough using the SS reg. what results in that all passed values are put onto stack or a pointer to them is put onto Stack.
Normally this space will be recovered by ending the routine, but when you do recursion then do it like this

     FUNCTION WITH_LOCALS_AND_PARAMS(VAR X,Y,Z:REAL;??:??);
      VAR A,B,C... : ????
      CONST .....
      ....
     
      VAR A,B,C... : ????
          x,y,z:REAL;
         RESULT:BOOLEAN;
      CONST .....
      ....

      PROCEDURE  WITHOUT_LOCALS_AND_PARAMS;
      Begin
       Your Code
      END.

Don't use Local Data use Global Data!
Don't use Parameters or transfer any values because they are eating stack like mad!

0
 
LVL 15

Expert Comment

by:VGR
ID: 8248773
sorry boy, but according to Master Wirth, a "properly written" recursive routine (function or procedure) uses ONLY parameter or local data.

That's also the only way to make it crystal-clear and to be sure it works with no "side effects" ;-)

Moreover, the Asker has no recursion in his/her program, so...
0
 
LVL 1

Expert Comment

by:Okey
ID: 8253049
To make recursive structure avoidable because of known problems the use of globalized Data will lead to functions representing the recursive-routine-heart and make it possible to avoid recursion!
0
 
LVL 15

Expert Comment

by:VGR
ID: 8253093
this is called "unrolling" a recursion. It's not always feasible, but always lead to ugly code 8-)

a well-written recursion is never a problem.
0
 

Author Comment

by:nislick
ID: 8263538
Cheers, found the problem was in the way i set up the recursion...first i removed the variables at the start of the procedure, then i changed the recursion into a while loop :)
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This is a fine trick which I've found useful many times, when you just don't want to accidentally run a batch script or the commands needs administrator rights.
An introduction to the wonderful sport of Scam Baiting.  Learn how to help fight scammers by beating them at their own game. This great pass time helps the world, while providing an endless source of entertainment. Enjoy!
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…

800 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question