python-栈溢出(stack overflow)问题解决方案
栈溢出(stack overflow)问题解决方案
场景:
eg:
Fatal Python error: Cannot recover from stack overflow
原因: 使用递归函数调用过多导致栈溢出。
在Python中,函数调用,通过栈(stack)实现;
当进入函数调用,相当于一次push压栈操作,每当函数返回,相当于一次pop出站操作。由于栈的大小不是无限的,所以递归调用次数过多,会导致栈的溢出。
Windows程序的内存机制大概是:
全局变量(局部的静态变量本质也属于此范围)存储于堆内存, 该段内存较大, 一般不会溢出;函数地址、参数、局部变量等信息存储于栈内存,栈内存较小容易发生溢出现象,但是效率较高。
总结:
- 函数递归调用层次过深,每次调用一次, 函数参数、局部变量等信息就压栈一次,并且没有及时出站;
- 局部变量体积太大;
解决方法
1、递归调用改用while 或者for 循环实现(推荐使用);
2、通过尾递归 + 生成器的方法;
3、改用堆内存, 函数定义很大的局部变量(eg: 大数组),此时局部变量可以改变为静态变量(或者全局变量);
4、增大栈的大小值。
尾递归+生成器
eg:
import types
def f_recursive(cur_i, cur_computer_result=1):
if cur_i == 1:
yield cur_computer_result
yield f_recursive(cur_i - 1, cur_i + cur_computer_result)
def f_recursive_wapper(generator, i):
gen = generator(i)
while isinstance(gen, types.GeneratorType):
gen = gen.__next__()
return gen
print(f_recursive_wapper(f_recursive,10000))
修改栈的大小
import sys
sys.setrecursionlimit(2000)
def f(i):
if i == 1:
return 1
return i + f(i -1)
result = f(999)
print(result)