如何修复 Lisp 中的堆栈溢出错误

Posted

技术标签:

【中文标题】如何修复 Lisp 中的堆栈溢出错误【英文标题】:How to fix a stack overflow error in Lisp 【发布时间】:2021-06-11 16:54:58 【问题描述】:

我这里有一个代码,它试图获取低于给定数字的所有素数的总和。当我运行它时,我不断收到堆栈溢出错误,仅此而已,而且我似乎找不到哪里出错了。

(format t "Enter your number ~%")

;global variables
(defvar *number* (read))

(defvar *conditional-check* nil)

(defvar *prime* nil)



;sum-of-primes function 
(defun sum-of-primes (x)
    (defvar sum 0)
    (primeCheck x 2)
    (if (equal *prime* 'yes) 
        (progn
            (setf sum (+ sum x))
            (setf z (- x 1))
            (conditional z)
            (if (equal *conditional-check* 'yes) (sum-of-primes z) ()))
        (and (setf z (- x 1)) (sum-of-primes z)))
)


;conitional function
(defun conditional (z)
    (if (>= z 1) (setf *conditional-check* 'yes) (setf *conditional-check* 'no))
)


;prime number check
(defun primeCheck (*number* y)
    (if (and (>= *number* y) (not (= (mod *number* y) 0))) 
        (progn 
            (setf z (+ y 1))
            (primeCheck *number* z)
            (setf *prime* 'yes))
    (setf *prime* 'no))
)

;function call
(sum-of-primes *number*)


【问题讨论】:

【参考方案1】:

sum-of-primes 缺少一些 基本条件,从而结束递归调用。这是主要问题,但是您的代码非常混乱,并且包含许多无用的全局变量。您应该避免使用全局变量并使用局部变量(由let 或函数调用创建)。对于此示例,您根本不需要任何全局变量。

(defun sum-of-primes (num)
  (sum-of-primes-help 0 num))

(defun sum-of-primes-help (i num)
  (cond ((= i num) 0)
        ((primep i) (+ i (sum-of-primes-help (+ i 1) num)))
        (t (sum-of-primes-help (+ i 1) num))))
         
(defun primep (num)
    (primep-help 2 num))

(defun primep-help (i num)
  (cond ((= num 0) nil)
        ((= num 1) nil)
        ((= i num) t)
        ((= 0 (mod num i)) nil)
        (t (primep-help (+ i 1) num))))

(defun program ()
  (format t "Enter your number ~%")
  (format t "Sum of primes is: ~s" 
          (sum-of-primes (read))))

那你就打电话给(program)

【讨论】:

非常感谢马丁。你的代码更整洁,更易读。我只是不明白这行代码的作用。 (t (sum-of-primes-help (+ i 1) num)) 对于这一行 (cond ((= i num) 0) 我知道我们将 i 设置为 num 但 0 用于【参考方案2】:

*** 意味着称为堆栈的内存部分已达到其限制。为了澄清,在堆栈上存储了函数调用。现在,如果存储函数调用的内存部分达到其限制,则意味着发生了太多的函数调用。这通常意味着无限递归。想象一个只调用自己的函数。现在,如果您调用该函数,则该调用将存储在堆栈中。但是,该函数调用自身,并且第二个调用也存储在堆栈中。而第二次调用是第三次调用该函数,该函数存储在堆栈中,以此类推。

可以通过查看函数本身调用的代码的特定区域来解决递归的这种错误使用,或者更广泛地说,如果函数已经在堆栈上,但它正在被调用再次调用。

这是您为找出当前问题的解决方案并避免将来出现类似问题所需的理解。

【讨论】:

以上是关于如何修复 Lisp 中的堆栈溢出错误的主要内容,如果未能解决你的问题,请参考以下文章

如何解决递归调用中的堆栈溢出错误?

C#:递归方法期间的堆栈溢出异常

python 修复了堆栈溢出问题的日历图的版本

Java 中的自调用函数中的堆栈溢出错误(岛数)

递归过程中的第一个过程调用发生堆栈溢出

怎么解决 LINUX 堆栈溢出内存的问题