Weird non-lisp errors with capturing labels with a lambda and `reduce`

99 Views Asked by At

I stumbled across a very weird bug (?) while I was developing an application in Allegro Common Lisp, v9.0 for Windows. I do not get the regular lisp errors, instead I get system errors encapsulated in a lisp condition. I managed to create a simple test-case to reproduce the error (it's very silly):

(defun lambda-producer ()
  (labels ((producer-label (x y)
                           (if (> x y) (- x y) (- y x)))
           (producer-label2 (x y)
                            (max (producer-label x 2) (producer-label y 3))))
  (lambda (x)
    (reduce (lambda (a b) (producer-label2 a b)) x))))

;; Get errors when calling:
(funcall (lambda-producer) (list 2 1 5 12))

I get a Stack overflow error for this test case every time I try it.

In my original code I got a plethora of errors, mostly segmentation faults, once a 'can not take car of <..> because it is not listp' and once Allegro crashed.

When running the same snippet (or my original code) in CLisp, everything runs fine and the REPL gives an answer.

My question: Am I doing something wrong or illegal here, or is there a bug in Allegro CL? If so, can we determine what that bug is and what to do about it?


Some experimentation seems to indicate that the reduce and double labels are essential in reproducing the error; replacing reduce with a funcall or if there is only one label does not give an error.

1

There are 1 best solutions below

1
On BEST ANSWER

This is a compiler bug. Please contact Franz.

CG-USER(8): (disassemble (lambda-producer))
;; disassembly of #<Closure Template Function (:INTERNAL LAMBDA-PRODUCER 0)>
;; formals: X
;; closure vectors:
;;      0: #<Closure (LABELS LAMBDA-PRODUCER PRODUCER-LABEL2) @ #xdfdda7a>
;;      1: #<Function (LABELS LAMBDA-PRODUCER PRODUCER-LABEL)>
;; constant vector:
0: #<Closure Template Function (:INTERNAL (:INTERNAL LAMBDA-PRODUCER 0) 0)>
1: REDUCE

;; code start: #x21869018:
   0: 55          pushl ebp
   1: 89 e5     movl    ebp,esp
   3: 83 ec 38  subl    esp,$56
   6: 89 75 fc  movl    [ebp-4],esi
   9: 89 5d e4  movl    [ebp-28],ebx
  12: 39 63 1a  cmpl    [ebx+26],esp
  15: 76 03     jbe 20
  17: ff 57 43  call    *[edi+67]      ; SYS::TRAP-STACK-OVFL
  20: 83 f9 01  cmpl    ecx,$1
  23: 74 03     jz  28
  25: ff 57 8b  call    *[edi-117]    ; SYS::TRAP-WNAERR
  28: 8b 5d 00  movl    ebx,[ebp+0]
  31: 8b 5b ec  movl    ebx,[ebx-20]
  34: 8b 5b fa  movl    ebx,[ebx-6]
  37: 80 7f cb 00 cmpb  [edi-53],$0        ; SYS::C_INTERRUPT-PENDING
  41: 74 03     jz  46
  43: ff 57 87  call    *[edi-121]    ; SYS::TRAP-SIGNAL-HIT
  46: 8b 56 12  movl    edx,[esi+18] ; #<Closure Template Function (:INTERNAL (:INTERNAL LAMBDA-PRODUCER 0) 0)>
  49: ff b7 43 fe pushl [edi-445] ; SYS::CLOSURE-HEADER
      ff ff 
  55: 8f 45 d0  popl    [ebp-48]
  58: ff b7 47 fe pushl [edi-441] ; SYS::CLOSURE-ADDRESS
      ff ff 
  64: 8f 45 d4  popl    [ebp-44]
  67: 89 55 d8  movl    [ebp-40],edx
  70: 89 5d dc  movl    [ebp-36],ebx
  73: 8d 5d e2  leal    ebx,[ebp-30]
  76: 89 c2     movl    edx,eax
  78: 89 d8     movl    eax,ebx
  80: 8b 5e 16  movl    ebx,[esi+22] ; REDUCE
  83: ff 57 27  call    *[edi+39]      ; SYS::TRAMP-TWO
  86: 89 7d f0  movl    [ebp-16],edi
  89: c9          leave
  90: 8b 75 fc  movl    esi,[ebp-4]
  93: c3          ret

;; disassembly of #<Closure Template Function (:INTERNAL (:INTERNAL LAMBDA-PRODUCER 0) 0)>
;; formals: A B

;; code start: #x2186ccc0:
   0: 55          pushl ebp
   1: 89 e5     movl    ebp,esp
   3: 83 ec 30  subl    esp,$48
   6: 89 75 fc  movl    [ebp-4],esi
   9: 89 5d e4  movl    [ebp-28],ebx
  12: 39 63 1a  cmpl    [ebx+26],esp
  15: 76 03     jbe 20
  17: ff 57 43  call    *[edi+67]      ; SYS::TRAP-STACK-OVFL
  20: 83 f9 02  cmpl    ecx,$2
  23: 74 03     jz  28
  25: ff 57 8b  call    *[edi-117]    ; SYS::TRAP-WNAERR
  28: 8b 5d 00  movl    ebx,[ebp+0]
  31: 8b 5b ec  movl    ebx,[ebx-20]
  34: 8b 5b fa  movl    ebx,[ebx-6]
  37: 80 7f cb 00 cmpb  [edi-53],$0        ; SYS::C_INTERRUPT-PENDING
  41: 74 03     jz  46
  43: ff 57 87  call    *[edi-121]    ; SYS::TRAP-SIGNAL-HIT
  46: ff 73 f6  pushl   [ebx-10]
  49: 8f 45 dc  popl    [ebp-36]        ; EXCL::|local-0|
  52: 8b 75 dc  movl    esi,[ebp-36] ; EXCL::|local-0|
  55: 89 fb     movl    ebx,edi
  57: b9 02 00 00 movl  ecx,$2
      00 
  62: ff 57 23  call    *[edi+35]      ; SYS::FUNCALL-TRAMP
  65: 89 7d f0  movl    [ebp-16],edi
  68: c9          leave
  69: 8b 75 fc  movl    esi,[ebp-4]
  72: c3          ret
  73: 90          nop

At 49 and 52 of the second closure template, you can see that it's feeding itself to sys::funcall-tramp1 with 2 arguments2.


  1. sys::funcall-tramp is an internal that I think might perform or otherwise allow tail calls.

  2. According to ecx at 57, since ecx is what seems to be used to check if the internal sys::trap-wnaerr is called; I suppose wna stands for wrong number of arguments.