美文网首页
翻译:Allocating more memory than t

翻译:Allocating more memory than t

作者: 东东东东东东丶 | 来源:发表于2018-05-31 19:30 被阅读0次

    Stack overflow地址:c++ - Allocating more memory than there exists using malloc - Stack Overflow

    翻译:

    下面的代码片段,每次从stdin中读取到字母'u'时就会分配2Gb的内存,一旦读取到'a'就会初始化所有分配的内存。

    #include

    #include

    #include

    #include

    #define bytes 2147483648

    using namespace std;

    int main()

    {

        char input [1];

        vector activate;

        while(input[0] != 'q')

        {

            gets (input);

            if(input[0] == 'u')

            {

                char *m = (char*)malloc(bytes);

                if(m == NULL) cout << "cant allocate mem" << endl;

                else cout << "ok" << endl;

                activate.push_back(m);

            }

            else if(input[0] == 'a')

            {

                for(int x = 0; x < activate.size(); x++)

                {

                    char *m;

                    m = activate[x];

                    for(unsigned x = 0; x < bytes; x++)

                    {

                        m[x] = 'a';

                    }

                }

            }

        }

        return 0;

    }

    我在一台有3Gb内存的linux虚拟机上运行这个代码。在使用htop工具监测系统内存使用情况,我意识到malloc操作并不影响资源。

    举个例子,当我只输入一次'u'时(分配2Gb的堆内存),我没有在htop上看到内存使用增加2Gb。只有当我输入'a'(初始化)时,我才看到内存使用的增加。

    因此,我可以“malloc”比实际更多的堆内存。举个例子,我可以malloc 6GB(这远大于我的ram和交换内存)并且malloc允许这么做(malloc没有返回NULL)。但是当我尝试初始化分配的内存时,我可以看到内存和交换内存被填满直到进程被杀死。

    我的问题:

    1.这是内核的bug吗?

    2.能有人给我解释下,为什么这种行为是允许的?


    Answers1:

    这叫 memory overcommit.。你可以以root用户关闭它:

    echo 2 > /proc/sys/vm/overcommit_memory

    这不是我喜欢的内核特性(所以我经常关闭它),看malloc(3)和 mmap(2)proc(5)

    NB:echo 0代替echo 2并不总是可行的。详情看文档(尤其是我连接的 proc man文档)


    Answers2:

    malloc的man文档(online here):

    默认的,Linux遵从积极的内存分配策略。这意味着当 malloc()返回非NULL时,并不保证内存时真正可用的。

    因此当你想要分配更多的时候,它在骗你,当你想要使用分配的内存时,它会为你尝试寻找足够的内存如果找不到足够内存它可能就会崩溃。


    Answers3:

    不,这不是内核的bug。你已经发现了一些知识被称为延迟页面(或者过量使用)。

    直到你写一个字节到使用malloc()分配的地址时,内核做的就是保留地址范围。这取决于你内存分配器和操作系统的实现,但是大多数内核在内存第一次使用之前不会触发过大的开销。

    实时操作系统像VxWorks不会允许这种行为,因为延迟页面导致严重的延迟。技术上,它就是将延迟延迟到稍晚的一个不确定的时间。

    对于更多细节的讨论,你可能会对IBM's AIX操作系统的处理方式感兴趣,page allocationovercommitment


    Answers4:

    这个结果是Basile提到的,过量使用内存。然而,这有一种有趣的解释。

    基本上,当时尝试在Linux(POSIX)上映射一块额外的内存时,内核仅仅保留它,只有你的应用程序访问其中一个保留页时才会最终使用它。这允许多个应用程序保留超过实际的 ram/swap的内存。

    这是一个令人满意的特性在大多数Linux环境中,除非你有一个实时操作系统或者在那些你确切的知道谁会需要资源,什么时候以及为什么。

    否则一个人可能一起过来,malloc超过ram内存的总量(实际上对它什么也不做)。

    另一个例子是mmap()的懒分配,在那里你有一个文件的虚拟映射放在里面,但是你只有一小块真正的内存用于这项工作。这将允许你mmap()一个巨大的文件(比你可用的RAM还要大),并且使用它就像正常的文件句柄那样,这是非常玩么的。


    Answers5:

    在使用内存的时候应该这么做:

    memset(m, 0, bytes);

    你也可以使用calloc,它不仅分配内存并且用0来填充它:

    char* m = (char*) calloc(1, bytes);

    相关文章

      网友评论

          本文标题:翻译:Allocating more memory than t

          本文链接:https://www.haomeiwen.com/subject/nnvxsftx.html