如何在python中导致堆栈溢出和堆溢出

Bug*_*tGG 5 python stack-overflow heap python-3.x

我试图了解python如何管理堆栈和堆.所以我想做一些"坏"编程并导致堆栈溢出和堆溢出.我不明白的是为什么字符串例如去堆叠而其他所有去堆.这只是设计师的一致意见吗?这些例子是否正确?从我所看到的内容中,python中的所有内容都是在堆中生成的,因为它面向对象,对吧?

编辑:我认为像C这样的语言的堆栈有一个固定的长度但在python中甚至堆栈是动态分配的,因为Anycorn在他的回答中说.这就是为什么如果我尝试一个大字符串(在堆栈上)或一个列表(在堆上)我也获得完整的内存.如果我错了,请纠正我.谢谢

来自http://docs.python.org/c-api/memory.html

Python中的内存管理涉及包含所有Python对象和数据结构的私有堆.Python内存管理器在内部确保对此私有堆的管理.Python内存管理器具有不同的组件,可处理各种 动态存储管理方面,如共享,分段,预分配或缓存.

在最低级别,原始内存分配器确保私有堆中有足够的空间通过与操作系统的内存管理器交互来存储所有与Python相关的数据.在原始内存分配器之上,几个特定于对象的分配器在同一堆上运行,并实现适合于每种对象类型的特性的不同内存管理策略.

这里有些例子.您可以将它们复制粘贴到Python官方可视化工具中,但使用较小的值会导致它无法运行...

对于堆栈溢出:

import time
word = "test "
x = word*1000000000
time.sleep(10)
print ("this message wont appear if stack overflow has occurred!") 
Run Code Online (Sandbox Code Playgroud)

我明白了

x = word*1000000000
MemoryError
Run Code Online (Sandbox Code Playgroud)

如果我删除一个零则运行.我使用时获得最大内存使用x = word*500000000 因此我无法使堆栈溢出,因为即使堆栈是动态分配的?

对于堆溢出:

i = 10000
test_list = [0]
while i > 0 :
    test_list [:0] = test_list #insert a copy of itself at the beginning
    i -= 1
Run Code Online (Sandbox Code Playgroud)

现在我不明白的是垃圾收集器如何在程序中启动.它是否在堆栈和堆上运行,因为它们都是动态分配的?是由于O/S内存管理器吗?这些事情告诉我们有关python编程语言的特征的什么?这是否可以证明"动态语言"或"解释"一词的合理性?很抱歉这个问题很长,但我只想澄清一些事情.提前致谢!

EDITED
我找到了我想要的东西:如果你sys.setrecursionlimit(N)用比你的系统实际处理的N值更大的值来调用你可以导致'真正的'堆栈溢出 ,然后尝试递归到那个深度.在某些时候,您的系统将耗尽堆栈空间,Python解释器将崩溃.

Wil*_*ill 7

通过构建一个无限递归的函数,你可以在python中很容易地导致堆栈溢出,就像在任何其他语言中一样.这在python中更容易,因为除了递归之外它实际上不需要做任何事情.

>>> def foo():
...     return foo()
... 

>>> foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  .......
  File "<stdin>", line 2, in foo
RuntimeError: maximum recursion depth exceeded
>>> 
Run Code Online (Sandbox Code Playgroud)

至于堆,由垃圾收集器管理.你可以分配大量的对象,并最终耗尽堆空间,Python会提出一个MemoryError,但这需要相当长的时间.你实际上是通过问题中的"堆栈溢出"示例来实现的.您在堆栈上存储了对字符串的引用,该字符串占用了进程可用的所有可用内存.根据经验,Python会在堆栈上存储对堆结构的引用,以获取无法保证大小的任何值.

至于它是如何工作的,从第一个例子可以看出,python对调用堆栈的深度有一个内置的限制,它不会超过它.可用于堆空间的内存量由OS定义,并且取决于许多因素.

这些应该是python文档的相应部分,用于错误本身的信息:


Any*_*orn 5

如果错误请纠正我:

据我所知,当涉及到实际的堆栈实现时,python堆栈(在默认分发中)实际上是基于堆内存(分配的内存malloc).因此,您不能导致堆栈溢出,但您可能会耗尽内存.你看到的计算机速度减慢是因为内存被交换到磁盘,程序非常慢.

通常,您不知道解释/字节编译语言如何实现其堆栈,但大多数情况下它并未在堆栈内存中实现,因此您不会导致堆栈溢出.可以使用Python实现alloca,但为什么呢?

参看 CPython - 在内部,存储在堆栈和堆上的内容是什么?

尝试使用编译语言,C++,Fortran等编译机器代码的相同实验.

  • @GeoPapas在非编译语言方面你必须区分程序调用堆栈和实际的机器内存堆栈 (3认同)