想象一下,您擁有“大”(32字節)的空閑內存空間:
---------------------------------- | | ----------------------------------
現在,分配其中一些(5個分配):
---------------------------------- |aaaabbccccccddeeee | ----------------------------------
現在,釋放前四個分配,但不釋放第五個分配:
---------------------------------- | eeee | ----------------------------------
現在,嘗試分配16個字節。糟糕,即使有那么多的免費,我也無法做到。
在具有虛擬內存的系統上,碎片化的問題比您想象的要少,因為大型分配只需要在虛擬地址空間中是連續的,而不需要在物理地址空間中是連續的。因此,在我的示例中,如果我的虛擬內存的頁面大小為2字節,那么我可以毫無問題地進行16字節分配。物理內存如下所示:
---------------------------------- |ffffffffffffffeeeeff | ----------------------------------
而虛擬內存(更大)可能看起來像這樣:
------------------------------------------------------... | eeeeffffffffffffffff ------------------------------------------------------...
內存碎片的經典症狀是,即使您似乎有足夠的可用內存,您也嘗試分配一個大塊而您卻無法分配。另一個可能的結果是該進程無法將內存釋放回OS(因為從OS分配的所有塊中仍然有一些對象在使用中,即使這些塊現在幾乎未使用)。
防止C ++中內存碎片的策略是根據對象的大小和/或預期壽命從不同區域分配對象來進行工作的。因此,如果要創建很多對象並在以后將它們全部銷毀,請從內存池中分配它們。您在它們之間進行的任何其他分配都不會來自池,因此不會在內存中位於它們之間,因此不會導致內存碎片。
通常,除非您的程序可以長時間運行並且需要大量分配和釋放,否則您不必為此擔心。在這種情況下,您面臨的風險最大的是短壽命和長壽命的混合物,但即使malloc
那樣,它也會盡最大努力提供幫助。基本上,請忽略它,直到您的程序出現分配失敗或意外導致系統內存不足(優先選擇在測試中捕獲!)。
標准庫不比分配內存的任何其他庫差,並且標准容器都有一個Alloc
模板參數,如果絕對必要,可以使用它們來微調其分配策略。