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

时间:2012-09-26 22:14:21

标签: python python-3.x heap stack-overflow

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

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

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

  

Python中的内存管理涉及包含所有内容的私有堆   Python对象和数据结构。这个私人的管理   Python内存管理器在内部确保堆。 Python   内存管理器有不同的组件处理各种    动态存储管理 等方面,例如共享,细分,   预分配或缓存。

     

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

以下是一些例子。您可以将它们复制粘贴到Python official visualizer中,但值较小会导致它无法运行...

堆栈溢出:

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

我得到了

x = word*1000000000
MemoryError

如果我删除一个零则运行。我使用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

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

EDITED
我找到了我要找的东西: 如果你打电话,你可以导致“真正的”堆栈溢出 值{N}大于系统实际可以处理的sys.setrecursionlimit(N)然后尝试递归到该深度。在某些时候,你的系统将耗尽堆栈空间,Python解释器将崩溃。

2 个答案:

答案 0 :(得分: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
>>> 

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

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

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

答案 1 :(得分:5)

如果错误,请纠正我:

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

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

比照。 CPython - Internally, what is stored on the stack and heap?

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