I'm using gpc 20010115 on a Linux system. I'm having problems with a program I've written which has recursive function calls, which I thought may be down to blowing the stack.
If I run the program in gdb, when it crashes I can't get it to display a backtrace:
Program received signal SIGSEGV, Segmentation fault. 0x240804e7 in ?? () (gdb) bt #0 0x240804e7 in ?? () Cannot access memory at address 0xbabffff5
So I compiled it with --stack-checking, and now it crashes much earlier, with a segmentation fault on a 'var' statement. It's at about 20 levels of recursion, and the function only uses three of four integers of local variables; uname -s tells me I have 8196k of stack, so I'm puzzled as to why I'm blowing the stack, if indeed I am.
Is a SIGSEGV what you would expect to see as a result of turning on stack checking? Are there any known problems in gpc in this area? Any suggestions as to what I can do to investigate further?
Steve
Steve Loft wrote:
I'm using gpc 20010115 on a Linux system. I'm having problems with a program I've written which has recursive function calls, which I thought may be down to blowing the stack.
If I run the program in gdb, when it crashes I can't get it to display a backtrace:
Program received signal SIGSEGV, Segmentation fault. 0x240804e7 in ?? () (gdb) bt #0 0x240804e7 in ?? () Cannot access memory at address 0xbabffff5
So I compiled it with --stack-checking, and now it crashes much earlier, with a segmentation fault on a 'var' statement. It's at about 20 levels of recursion, and the function only uses three of four integers of local variables; uname -s tells me I have 8196k of stack, so I'm puzzled as to why I'm blowing the stack, if indeed I am.
Without seeing the code I can only guess. GPC uses stack, e.g., for temporary expressions. Strings (and large sets), in particular, can eat up much stack rather quickly.
You can use the built-in (since 2000-04-11) routine FrameAddress to get the current stack (frame) position. If you check it in some critical routines, you might be able to get an idea how much stack is used in each call.
program WasteStack;
procedure Recursive; begin Writeln (PtrCard (FrameAddress (0))); Recursive end;
begin Recursive end.
If it turns out that, say, most of the stack waste is due to a complicated string operation in the recursive routine, you could solve the problem by encapsulating it in a local subroutine (which will return, and therefore free its temporary storage, before the recursive call).
Is a SIGSEGV what you would expect to see as a result of turning on stack checking?
Depends on the OS, I think. On Linux, it's SIGSEGV, on some other systems it might also be SIGBUS etc...
Frank
On Thursday 25 January 2001 7:38 pm, Frank Heckenbach wrote:
You can use the built-in (since 2000-04-11) routine FrameAddress to get the current stack (frame) position. If you check it in some critical routines, you might be able to get an idea how much stack is used in each call.
Thanks, Frank. So far I haven't been able to discover much from using FrameAddress, but from experimenting a bit it does seem to point to a stack problem. For example, if I declare a large array inside one of the recursive procedures, the segmentation fault occurs much earlier.
I'm not doing anything complicated with strings, but one thing I have realised which might be relevant is this: My recursive procedures are nested - could this be causing a problem? The structure of the recursive part of my program is something like this:
procedure outer(...); var .....;
procedure recursive_one(...); var ....;
procedure recursive_two(...); var ...;
begin if {something} then recursive_two else {something else} end; begin { recursive_one } if {something} then recursive_one(...) else recursive_two(...) end; begin { outer } recursive_one(...) end; Could the fact that recursive_two is inside recursive_one be causing problems when recursive_one calls itself?
Steve
Steve Loft wrote:
Thanks, Frank. So far I haven't been able to discover much from using FrameAddress, but from experimenting a bit it does seem to point to a stack problem.
What are the figures? How many bytes of stack are used in each level? Is it more than you expected? Does the total bytes used actually exceed the resource limit? (Otherwise the problem might be something else after all, like an "ordinary" out of range access.)
Could the fact that recursive_two is inside recursive_one be causing problems when recursive_one calls itself?
Not by itself. Of course, indirect recursive calls means more active frames on the stack, but if they're all small, the sum should still be small.
Frank
Hi Frank
How do you change the default size of the stack?
Borland has $M but couldn't find an equivalent in either gcc or gpc info pages. ( Perhaps I overlooked it )
Thanks Russ
Russ Whitaker wrote:
How do you change the default size of the stack?
Borland has $M but couldn't find an equivalent in either gcc or gpc info pages. ( Perhaps I overlooked it )
For DJGPP, you can use something like this (or use stubedit):
{$ifdef DJGPP} const MinStackSize : Cardinal = $400000; asmname '_stklen'; {$endif}
On Unix-like systems, you can set a resource limit, but you don't do it in normal programs, but rather in the shell settings. (bash: ulimit; csh: limit; syscall: setrlimit(2))
DJGPP has to allocate the stack in physical memory at program startup, so one might have to be careful with too large stack limits. Most other systems allocate stack pages on demand, so the only reason to set a limit at all might be to prevent a runaway recursion from eating up all memory...
Frank
Hello,
Steve Loft wrote:
If I run the program in gdb, when it crashes I can't get it to display a backtrace: [...]
Did you supply the -g option when compiling?
gpc --automake -g foo.pas -o foo
You can turn on optimization if you wish, but you must not strip the symbol table (option -s). With -s or without -g you do not get a backtrace in GDB.
For more specific help, we need the source of the program in question.
Hope this helps,
Peter