Segmentation fault

Windows specific questions.
Post Reply
Macq
Posts: 24
Joined: Feb 18, 2021 4:01
Location: Queensland, Australia

Segmentation fault

Post by Macq »

I was testing the speed of some sort functions, when I ran into this annoying behavior:

Code: Select all

' Tickle a segfault
const NUMDATA  =  50000   ' Segfault(!)
'dim as integer NUMDATA=50000 ' OK
dim as string sQ(NUMDATA)
dim as string sB(38000) ' 37000 OK.  38000 Segfault(!)
I'm using FreeBASIC-1.09.0-winlibs-gcc-9.3.0 and compiling for Win64 Console (Release) using WinFBE on Windows10 English, Australia.
SARG
Posts: 1756
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Segmentation fault

Post by SARG »

Just because there is an overflow in the stack.

A string datatype needs 24 bytes (without counting the string itself not on the stack).
The stack is by defaut 2Mo on 64bit.

(50000+38000) x 24 = 2 112 000 bytes so greater than the default stack size 2 097 152

You can use shared or increase the stack size ( -t compiler option ).
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Segmentation fault

Post by fxm »

Or use dynamic (var-len) arrays which are always stored in the heap:

Code: Select all

const NUMDATA  =  50000
redim as string sQ(NUMDATA)
redim as string sB(38000)
badidea
Posts: 2586
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Segmentation fault

Post by badidea »

Unfortunately, the compiler is not smart enough to understand that the 2 arrays together are too large for the stack.
If you have this code, you do get a warning at compile time:

Code: Select all

const NUMDATA  =  50000
dim as string sQ(NUMDATA + 38000)
test.bas(3) warning 23(2): Array too large for stack, consider making it var-len or SHARED
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Segmentation fault

Post by paul doe »

badidea wrote: Feb 25, 2022 11:31 Unfortunately, the compiler is not smart enough to understand that the 2 arrays together are too large for the stack.
...
Indeed. I haven't checked how fbc performs constant folding, but using a constant and a literal in the dimensions does produce an array in the stack (since the expression ends up being constant as well). Note that this is effectively what fxm's code does (he uses redim instead of dim). Another way of expressing that could be:

Code: Select all

const NUMDATA  =  50000

dim as string sQ()
redim sQ(NUMDATA + 38000)
Macq
Posts: 24
Joined: Feb 18, 2021 4:01
Location: Queensland, Australia

Re: Segmentation fault

Post by Macq »

Thanks for the quick replies.

Perhaps the compiler can get smarter and keep a running total estimate of stack use by variables and either issue a warning or silently move the variables to the heap. Why are large arrays ever put on a limited stack anyway?

On a side note, Quicksort is only about 6 times faster than Bubblesort and the speed ratio doesn't improve with large numbers of data elements. I was surprised.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Segmentation fault

Post by fxm »

fxm wrote: Sep 27, 2020 6:48
fxm wrote:The FreeBASIC compiler does not add code to check at runtime the available memory in the system stack (even with the -exx compile option).
Only at compile time it roughly estimates if for each local static array there is no overflow of the system stack but without taking into account the stack memory needed for other local variables in the scope (including the other local arrays in the scope).
Compiler warning occurs only for each local static array strictly greater than the complete system stack size.

Otherwise, see FAQ: Why does my program crash when I define an array larger than xx?
Furthermore, I am not talking here about taking into account the procedure calls (with saving registers and passing parameters) which are generally very numerous and therefore very nested. And what about recursive calls!
St_W
Posts: 1619
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: Segmentation fault

Post by St_W »

Macq wrote: Feb 25, 2022 23:51On a side note, Quicksort is only about 6 times faster than Bubblesort and the speed ratio doesn't improve with large numbers of data elements. I was surprised.
With Quicksort having an average complexity of O(n*log(n)) and Bubblesort having an average complexity of O(n²) this can't really be true in general. Maybe you have special data (e.g. already roughly sorted) or your implementation is somehow buggy.
SARG
Posts: 1756
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Segmentation fault

Post by SARG »

With 5 lines of code, I added a check in gas64 for throwing an error at compile time if the stack will be overflowed, independently for each procedure.
BUT only with gas64 as the stack size needs to be defined for procedures when emitting the assembly code.

A raw result with the Macq's code (first post) :

Code: Select all

D:\compiler108\freebasic64bit\fbc64_gas64 -R -v -gen gas64 test_stack.bas
FreeBASIC Compiler - Version 1.09.0 (2022-01-09), built for win64 (64bit)
Copyright (C) 2004-2021 The FreeBASIC development team.
standalone
target:       win64, x86-64, 64bit
backend:      gas64
compiling:    test_stack.bas -o test_stack.asm (main module)
test_stack.bas() error 0:    STACK OVERFLOW, review array size, use redim/shared or increase stack size, for proc=main"
Now I have to discuss with Jeff as it's only with gas64 (maybe also possible with gas32).

I believe it's possible to do a check at run time each time a new procedure is started and so generate a run time error. I just need a bit of time to confirm/infirm.
adeyblue
Posts: 299
Joined: Nov 07, 2019 20:08

Re: Segmentation fault

Post by adeyblue »

Instead of needing special code in multiple generators containig runtime checks slowing everything down for such an unlikely occurance (especially since it's going to crash anyway), just make the crash handler do a bit better than
oops lol
Be infinitely more helpful in far more situations, and cost no performance
On linux you can even use backtrace (and that useless unwind data :D) to print the address of the crash, since signal() is too pants to give you any info
SARG
Posts: 1756
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Segmentation fault

Post by SARG »

@adeyblue
Where and Why are two different things :-)
For example with the small code of first page (5 lines) the OP knew where the problem is but not why. You and I are enough skilled to understand quickly what is happening but not a newbee so more information doesn't hurt.

What I would do is adding the extra code (not so ressource consumming, see below) only if -exx option is selected and use the existing mechanism of stopping execution.

Only with gas64 as all necessary data is available.

Code: Select all

Begin of procedure
	add totalSizeStack,procSizeStack
	cmp totalSizeStack,maxSizeStack
	jg label
	call errorRuntime
	labal
	
End of procedure
	sub totalSizeStack,procSizeStack
Post Reply