簡體   English   中英

為什么600MB后動態內存分配失敗?

[英]why does dynamic memory allocation fail after 600MB?

我使用三維char數組實現了布隆過濾器(位表),直到到達無法再分配內存並發出bad_alloc消息的位置時,它才能正常工作。 分配600MB后,在下一個擴展請求中會出現此錯誤。

Bloom過濾器(陣列)預計將增長到8到10GB。

這是我用來分配(擴展)位表的代碼。

unsigned char ***bit_table_=0;
unsigned int ROWS_old=5;
unsigned int EXPND_SIZE=5;


void expand_bit_table()
     {
         FILE *temp;
         temp=fopen("chunk_temp","w+b");
         //copy old content
         for(int i=0;i<ROWS_old;++i)
             for(int j=0;j<ROWS;++j)
                 fwrite(bit_table_[i][j],COLUMNS,1,temp);
         fclose(temp);
         //delete old table
         chunk_delete_bit_table();
         //create expanded bit table ==> add EXP_SIZE more rows
         bit_table_=new unsigned char**[ROWS_old+EXPND_SIZE];
         for(int i=0;i<ROWS_old+EXPND_SIZE;++i)
            {
                bit_table_[i]=new unsigned char*[ROWS];
                for(int k=0;k<ROWS;++k)
                    bit_table_[i][k]=new unsigned char[COLUMNS];
            }
         //copy back old content

          temp=fopen("chunk_temp","r+b");
         for(int i=0;i<ROWS_old;++i)
         {
            fread(bit_table_[i],COLUMNS*ROWS,1,temp);
         }
          fclose(temp);
         //set remaining content of bit_table_to 0
         for(int i=ROWS_old;i<ROWS_old+EXPND_SIZE;++i)
             for(int j=0;j<ROWS;++j)
                 for(int k=0;k<COLUMNS;++k)
                     bit_table_[i][j][k]=0;

         ROWS_old+=EXPND_SIZE;
     }

數組的最大允許大小是多少,如果這不是問題,我該怎么辦。

編輯:它是使用32位平台開發的。

它在具有8GB RAM的64位平台(服務器)上運行。

一個32位程序必須從虛擬內存地址空間分配內存。 它存儲代碼和數據的大塊,並從它們之間的空洞中分配內存。 是的,您可以期望的最大值約為650 MB,這是最大的可用漏洞。 從那開始迅速下降。 您可以通過使數據結構更智能來解決它​​,例如樹或列表,而不是一個巨型數組。

您可以使用SysInternals的VMMap實用程序對進程的虛擬內存映射進行更多了解。 您可能可以更改DLL的基地址,以使它不會垂直位於地址空間的其他空白區域的中間。 但是,您將獲得超過650 MB的內存的可能性很小。

在64位操作系統上還有更多的喘息空間,由於操作系統組件以64位模式運行,因此32位進程具有4 GB的地址空間。 您必須使用/ LARGEADDRESSAWARE鏈接器選項,以允許該進程全部使用它。 盡管如此,這僅適用於64位操作系統,您的程序仍可能在32位操作系統上崩潰。 當您確實需要那么多VM時,最簡單的方法就是將64位OS作為先決條件,然后針對x64構建程序。

理論上,一個32位進程可以訪問的最大內存數據為4GB(實際上,它會更小一些)。 因此,您無法一次在內存中存儲10GB數據(即使操作系統支持更多數據)。 同樣,即使您正在動態分配內存,可用的可用存儲空間也進一步受到堆棧大小的限制。

進程可用的實際內存取決於生成可執行文件的編譯器設置。

如果確實需要那么多數據,請考慮將數據(部分)保留在文件系統中。

32位計算機為您提供4GB的地址空間。

操作系統會保留其中一部分(Windows默認情況下為一半,給您2GB的空間。我不確定Linux,但我相信它會保留1GB的空間)

這意味着您自己的進程有2-3 GB的空間。

進入這個空間,需要滿足以下幾點:

  • 您的可執行文件(以及所有動態鏈接的庫)都被映射到其中
  • 每個線程需要一個堆棧

還有很多其他堅韌不拔的東西。

關鍵是,最終實際使用多少內存並不重要。 但是許多不同的部分必須適合此存儲空間。 而且由於它們沒有緊密地包裝在一端,因此它們會分散存儲空間。 為簡單起見,請想象一下,您的可執行文件已映射到該內存空間的中間。 這會將3GB分成兩個1.5GB的塊。 現在說您加載了兩個動態庫,它們將這兩個塊細分為四個750MB。 然后,您有幾個線程,每個線程都需要更多的內存,將剩余的區域進一步分割。 當然,實際上,這些內存中的每一個都不會放在每個連續塊的確切中心(這是一個非常愚蠢的分配策略),但是,所有這些內存塊都會細分可用的內存空間,從而將其削減分成許多小塊。

您可能有600MB的可用內存,但是很可能沒有600MB的連續內存。 因此,如果幾乎可以肯定一個600MB分配失敗,那么六個100MB分配可能會成功。

您可以分配多少內存沒有固定限制。 答案是“取決於”。 這取決於進程的內存空間的精確布局。 但是在32位計算機上,您不可能一次分配500MB或更多。

暫無
暫無

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

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