[英]max malloc size lower than expected
這是一個檢查最大 malloc 大小的簡單程序:
#include <iostream>
std::size_t maxDataSize = 2097152000; //2000mb
void MallocTest(void*& ptr)
{
while (1)
{
ptr = malloc(maxDataSize);
if (ptr)
{
std::cout << "Malloc success: " << maxDataSize << std::endl;
return;
}
maxDataSize -= 1024;
if (maxDataSize <= 0)
{
return;
}
}
}
int main()
{
void* ptr = nullptr;
MallocTest(ptr);
if (ptr)
{
free(ptr);
}
system("pause");
return EXIT_SUCCESS;
}
我使用 Windows 10 x64 和 Visual Studio 2017。當我運行該程序時,我成功獲得了 ~1300mb 的 malloc 調用。 該程序使用 32 位架構(發布模式)構建,因此理論上內存限制等於 2GB。 有什么會導致內存碎片嗎? 為什么我不能分配超過 ~1300mb ?
注意:此答案的大部分內容是在 OP 指出他們使用的操作系統之前編寫的。 這些概念仍然有效,但具體情況可能有所不同。
你說你的操作系統是 32 位的,確實一個好的32 位實現會有 2 GB 的硬限制,因為大於PTRDIFF_MAX
對象有很多微妙的問題,當你使用它們時很容易導致未定義的行為,並觸發編譯器處理指針算法的錯誤。 但是,您已經達到了一些較低的限制因素。
在 Linux 上,當 32 位進程在 64 位內核上運行時,32 位進程的虛擬地址空間限制在大多數架構上為 3 GB,在某些架構上為 2 GB,而在某些架構上為 4 GB。 然而,在這個空間中,已經映射了許多東西,它們將地址空間分割並限制任何連續范圍的長度。 這包括程序本身,如果它是動態鏈接的,則包括動態鏈接器和它使用的任何共享庫。
如果您的程序不是構建為 PIE(位置無關可執行文件),則它在 Linux/x86 上的默認基址為 128 MB。 這將拆分地址空間的前 128 MB,因為它不能用於連續的上部。 庫通常在地址空間上限以下加載,從那端分離出一些,但可能不會太多。 ASLR(地址空間布局隨機化)可能會將它們向下移動一點,但主線內核不會這樣做太多,以避免嚴重碎片化已經非常有限的地址空間。 一些為額外加固而打補丁的內核可能會隨機化得更多。
最終,在 32 位系統上無法可靠地提供大量連續分配(大於半 GB 左右,甚至可能更少)。 如果您需要它們,您可能需要使用 64 位系統。 但更好的選擇可能是找出不需要連續分配的替代數據結構,甚至可以處理不適合內存的數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.