I'm trying to create a recursive user defined function with GnuCOBOL 2.0.0 but when I try to run the caller program it crashes with a "segmentation failure" error.
This is the function:
identification division.
function-id. FATORIAL.
author. Paulo Andre Dias.
date-written. 15/02/2017.
remarks. Calcula o fatorial do numero N informado via argumento.
environment division.
configuration section.
data division.
working-storage section.
77 ws-fatorial-n-menos-1 pic 9(006) value zeros.
linkage section.
01 lk-n pic 9(006).
01 lk-fatorial pic 9(006).
procedure division using lk-n returning lk-fatorial.
principal.
if lk-n = zeros
move 1 to lk-fatorial
else
move FATORIAL(lk-n - 1) to ws-fatorial-n-menos-1
compute lk-fatorial = lk-n * ws-fatorial-n-menos-1
end-if
goback.
end function FATORIAL.
This is the caller program:
identification division.
program-id. gtc002.
environment division.
configuration section.
repository.
function FATORIAL.
data division.
working-storage section.
77 ws-n pic 9(006) value zeros.
procedure division.
main.
display "Entre com um numero inteiro positivo (ou zero para encerrar):"
accept ws-n from console
if ws-n = zeros
stop run
else
display "O fatorial de " ws-n " e' " FATORIAL(ws-n)
end-if
go to main.
And this is what happens:
[aeisxpad ~/cbl]$ ../bin/gtc002
Entre com um numero inteiro positivo (ou zero para encerrar)::
5
Falha de segmentação
[aeisxpad ~/cbl]$
Am I missing something? Any ideas?
Thank you all in advance.
Workaround for a bug with User Defined Functions and GnuCOBOL.
User defined FUNCTION calls are not properly marshaled in terms of BINARY and DISPLAY usage. Values are passed as usage DISPLAY with pic 9. Try changing
ws-n
to USAGE BINARY. That will force a native numeric in the call, (which then needs to match in the linkage section oflk-n
in FATORIAL itself.and
Giving here,
Excuse the slight reformatting, the version above should work as FIXED or FREE format COBOL compiles
The original is passing an ASCII "00005" to the function, attempting to recurse a huge number of times when improperly marshaling as USAGE BINARY (it's a bug in GnuCOBOL). As @Simon Sobisch noted, this will be fixed someday, but a sound workaround for now is coding user defined functions with actual USAGE BINARY arguments for numerics instead of PIC 9 COBOL fields.
That work around will hold for recursive or non recursive functions.
With literals in source, use
FUNCTION NUMVAL(123)
for 123. The source text literal defaults to "123" PIC 9 (usage DISPLAY) form in GnuCOBOL cobc, and you need to force a USAGE BINARY numeric when calling User Defined Functions in current releases.