2015-10-13 26 views
1

心中已經混合模式應用程序,它是32倍。所以只有2G的內存可用。應用程序處理一些大型數據,並在非託管堆中分配約1.5G的數據。然後釋放分配的非託管內存而不泄漏。但下一步是在託管模式下處理大約1.5G。當試圖在List中添加約200M的託管內存時,應用程序崩潰。正如我所想的那樣,非託管堆管理器爲1.5G抓取內存,在其中分配對象,然後釋放對象,但不釋放堆內存以便可訪問託管堆管理器。託管和非託管內存管理器如何共享進程的內存?我該如何解決這個問題?內存管理在C++混合模式應用

這裏試圖分配和釋放非託管代碼後,分配管理內存時會拋出異常的示例代碼。它必須在x32中編譯。爲什麼會發生?

  int size = 1024 * 1024 * 1024/2/10; 

      char* * cppArray = new char*[size]; 

      for(int i = 0; i < size - 1; i++) 
      { 
       char *str = (char*)malloc(10 * sizeof(char)); 
       strcpy(str, "AAAAAAAAAA"); 
       cppArray[i] = str; 
      } 

      for(int i = 0; i < size - 1; i++) 
      { 
       char* str = cppArray[i]; 
       free(str); 
      } 

      delete[] cppArray; 

      List<String^>^ pArray = gcnew List<String^>(); 

      size = 1024 * 1024 * 1024/2/7/2/2; 

      for(int i = 0; i < size - 1; i++) 
      { 
       pArray->Add(gcnew String("AAAAAAAAAA" + i.ToString())); 
      } 

謝謝。

+0

你必須要考慮的方式託管代碼分配內存。如果您使用的是列表(每個元素都有一個節點),則必須考慮該列表的開銷(更不用說其他一些C#可能具有的matadata)。因此,對於一個列表節點,你存儲一個值和一個指向下一個列表節點的指針,這意味着如果你想要1.5GB的數據,你最終可能會得到另外1.5GB的總共3GB的指針。還有一些堆內存頭也增加了一些開銷。 – Raxvan

+0

如果在非託管之前使用託管堆,會發生什麼情況?你能爲列表分配內存嗎? – Alexander

+0

謝謝。是的,我很清楚託管代碼如何分配內存並進行考慮。應用程序處理兩組數據。由於分區問題,一組處於非管理模式。另一組採用新代碼的託管模式。我們重構應用程序進行管理。但現在它混合。在託管代碼中,它將使用大約1G-1.5G的所有託管開銷。 –

回答

0

在第一部分,無論是一次malloc分配撐mallaoc'ed。原因在於malloc()從操作系統獲取內存的方式,即增加堆最大地址。因此,爲了再次發佈它,您必須確保沒有更多的引用到那裏的任何地址,否則您會遇到段錯誤。

現在有解決的辦法是威力工作即mmap()發現無論它在MS叫說話使用mmap()分配器,或。確保它可以再次釋放它,例如munmap()

分配你的數據在memmapped地址,並確保你取消映射它之前,它沒有提及離開了。

ps。 也像@JSF說與LargeAddressAware編譯並啓用3GB在您的操作系統。 即使在32位系統上也要保證至少有4GB內存,操作系統會使用一些用戶無法訪問的內存。即使程序也只能訪問真正快速加起來超過3GB的3GB。