簡體   English   中英

如何在python中導致堆棧溢出和堆溢出

[英]How to cause stack overflow and heap overflow in python

我試圖了解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!") 

我明白了

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
我找到了我正在尋找的東西:如果你調用sys.setrecursionlimit(N) ,其值大於系統實際可以處理的N值,那么你可以導致“真正的”堆棧溢出,然后嘗試遞歸到那個深度。 在某些時候,您的系統將耗盡堆棧空間,Python解釋器將崩潰。

通過構建一個無限遞歸的函數,你可以在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文檔的相應部分,用於錯誤本身的信息:

如果錯誤請糾正我:

據我所知,當涉及到實際的堆棧實現時,python堆棧(在默認分發中)實際上是基於堆內存(使用malloc分配的malloc )。 因此,您不能導致堆棧溢出,但您可能會耗盡內存。 你看到的計算機速度減慢是因為內存被交換到磁盤,程序非常慢。

通常,您不知道解釋/字節編譯語言如何實現其堆棧,但大多數情況下它並未在堆棧內存中實現,因此您不會導致堆棧溢出。 可以使用alloca實現Python,但為什么呢?

參看 CPython - 在內部,存儲在堆棧和堆上的是什么?

嘗試使用編譯語言,C ++,Fortran等編譯機器代碼的相同實驗。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM