簡體   English   中英

最大 malloc 大小低於預期

[英]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.

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