jsk-ros-pkg / jsk_roseus

ROS EusLisp Client
http://wiki.ros.org/roseus/Tutorials
17 stars 56 forks source link

segmentation fault in `json-encode-element` in roseus_mongo #617

Closed HiroIshida closed 5 years ago

HiroIshida commented 5 years ago

I'm using json-encode-element function of roseus/roseus_mongo defined here.

When I pass an alist that has large size list as a value to the function, segmentation fault error occurs.

(load "package://roseus_mongo/euslisp/json/json-encode.l")
(defun zeros (N)
  (let ((lst nil)) (dotimes (i N lst) (push 0 lst))))

(defun save-json-test (N) 
  (let ((alist `((:x . ,(zeros N))))
        (filename "tmp"))
    (let ((out (open filename :direction :output)))
      (json::encode-element alist out)
      (close out))))

(defun output-json-test (N)
  (let ((alist `((:x . ,(zeros N))))
        (filename "tmp"))
    (json::encode-element alist *standard-output*)))

The both save-json-test and output-json-test work fine unless N is large. However, when I set N=10000 or larger for example, the both cause segmentation fault errors.

Affonso-Gui commented 5 years ago

Apparently we are having a problem with euslisp handling long recursive functions (event being tailed ones)

(defun test (l)
  (let ((i 0))
    (labels ((r-encode-list (l)
               (incf i)
               (when (cdr l) 
                 (r-encode-list (cdr l)))))
      (r-encode-list l) i)))

(test (make-list 10000 :initial-element 0))
;; segmentation fault

This should be a somewhat deem problem, so for now why don't you try to overwrite the encode-list using dolist instead?

c.f.

(defun test2 (l)
  (let ((i 0))
    (dolist (val l)
      (incf i))
    i))

(test2 (make-list 100000 :initial-element 0))
;; ok
HiroIshida commented 5 years ago

Thanks @Affonso-Gui for resolving the issue. Following your suggestion, I overrode the encode-list function by the following function:

(defun encode-list (lst_ &optional (os *standard-output*))
  (let ((lst (append lst_ '(:end))))
    (with-blacket os #\[ #\]
                  (dolist (elem lst)
                    (encode-element elem os)
                    (unless (eq elem :end) (write-byte #\, os))))))

and it works fine as expected.