iT邦幫忙

2024 iThome 鐵人賽

DAY 20
0

最近兩個主題我們談到了「堆疊 (Stack)」和「堆積 (Heap)」,即使它們在中文上只有一字之差,但在電腦科學中,它們的用途和特性是非常不同的。

1. 堆疊 (Stack)

堆疊是一種後進先出(LIFO, Last In, First Out)的資料結構。想像一下疊盤子,最後放上去的盤子會是第一個拿走的。電腦在執行程式時,特別是處理函數呼叫和局部變數時,會使用堆疊。

特性:

  • 記憶體分配方式: 靜態分配,通常使用固定大小。
  • 應用場景: 儲存局部變數、函數呼叫資訊、函數回傳位址等。
  • 存取方式: 透過指標(stack pointer)控制,按順序進行。
  • 效能: 因為是後進先出,所以執行速度很快且記憶體管理簡單。

2. 堆積 (Heap)

堆積則是用來動態分配記憶體的區域。當程式需要分配記憶體,但無法預先確定需要多大空間時,會向堆積申請記憶體。不同於堆疊,堆積的存取是無序的。

特性:

  • 記憶體分配方式: 動態分配,不固定大小,由程式運行時申請和釋放。
  • 應用場景: 儲存動態分配的變數,像是大型物件或需要在函數之間傳遞的資料。
  • 存取方式: 由作業系統或程式負責管理,通常透過指標來存取。
  • 效能: 因為需要動態分配和釋放記憶體,操作速度相對較慢,而且需要避免記憶體洩漏。

3. 異同點詳細分析:

  • 記憶體分配方式

    堆疊 (Stack):

    • 分配方式: 靜態分配,記憶體大小是事先在編譯時期就確定的,每次函數呼叫或區塊執行時,堆疊中的記憶體會依據既定大小自動分配。
    • 使用限制: 有固定大小,通常由作業系統定義,超出堆疊大小(如遞迴過深)會導致堆疊溢位(Stack Overflow)

    堆積 (Heap):

    • 分配方式: 動態分配,大小和存活時間不是事先確定的。程式運行時,根據需求向作業系統請求記憶體,並用完之後再手動釋放(如使用 newmalloc() 等)。
    • 使用限制: 理論上可以使用的記憶體很大,但動態記憶體分配過程中容易發生記憶體碎片化記憶體洩漏
  • 存取順序與方式

    堆疊 (Stack):

    • 存取方式: 後進先出(LIFO)。最後被放入堆疊的變數會最先被取出。堆疊指標(Stack Pointer)控制記憶體的分配與釋放,每次函數返回時自動釋放記憶體。
    • 存取效率: 因為堆疊操作是按順序進行,操作非常高效(時間複雜度是 O(1)),不需要額外管理。

    堆積 (Heap):

    • 存取方式: 無特定順序,通過指標直接存取。程式可以在任何時候對堆積中的任意記憶體進行存取。
    • 存取效率: 動態分配記憶體需要額外時間管理,因此速度較慢。存取記憶體時,需要尋址和管理記憶體區塊,因此效率不如堆疊高。
  • 生命週期

    堆疊 (Stack):

    • 生命週期: 自動管理。當程式進入函數時,函數的局部變數自動分配到堆疊上,函數返回後自動釋放。不需開發者手動干預。
    • 存活時間: 局部變數的生命週期與函數或區塊的執行時間相同,當結束時,變數就被自動清除。

    堆積 (Heap):

    • 生命週期: 需要手動管理。程式需要自行分配和釋放記憶體。如果未能正確釋放記憶體,會導致記憶體洩漏
    • 存活時間: 動態分配的變數可以在函數結束後繼續存在,直到程式主動釋放記憶體(例如使用 deletefree())。
  • 應用場景

    堆疊 (Stack):

    • 主要用途: 儲存函數的局部變數、參數、返回位址和控制流程。適用於短期、快速且固定大小的資料,像是簡單的數字或小型陣列。
    • 常見例子: 遞迴呼叫、函數的局部變數、函數呼叫時的返回地址。

    堆積 (Heap):

    • 主要用途: 動態分配大型物件或不確定大小的資料,適合用來存儲需要在整個程式中長時間存在的資料(例如大型物件、動態資料結構如鏈結串列、樹或圖等)。
    • 常見例子: 動態分配的陣列或物件、需要在多個函數之間傳遞的大型資料。
  • 效能

    堆疊 (Stack):

    • 效能高: 堆疊的操作非常簡單,記憶體管理是自動化的,不需要額外的開銷。函數返回時,局部變數自動釋放。

    堆積 (Heap):

    • 效能較低: 需要額外的處理來分配和釋放記憶體。使用堆積進行記憶體操作時,記憶體碎片化和洩漏問題需要額外管理,因此效能不如堆疊。

總結

  1. 堆疊 (Stack) 適合簡單、短期且大小固定的資料,具高效且自動的記憶體管理。像是你在書桌上堆疊書本,有明確的順序和操作規則。
  2. 堆積 (Heap) 更靈活,適合大型且不確定大小的資料,記憶體管理由開發者手動處理。像是你的書架,你可以隨時從任何位置拿取或放回書籍,但管理起來需要更多的計劃和精力。

參考資料:

  1. 詳解 Stack 與 Heap 之間的特性與差異 - Medium by Austin
  2. Java 面試 - JVM 的 Stack 和 Heap 請比較 JVM 記憶體的 Stack 和 Heap - Laugh Now by markleetw

上一篇
Day19 Stack題目3:739. Daily Temperatures
下一篇
Day21 演算法介紹:矩陣(Matrix)
系列文
Java刷題B:Leetcode Top 100 Liked30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言