zoukankan      html  css  js  c++  java
  • malloc一次性最大能申请多大内存空间

    受用户态内存地址空间的限制。64 位系统下分配几个 T 不成问题。

    著作权归作者所有。
    商业转载请联系作者获得授权,非商业转载请注明出处。
    作者:zz matrix
    链接:http://www.zhihu.com/question/20836462/answer/22833295
    来源:知乎

    考虑32位linux情况的话,依据版本的话
    如果是2.4版本之前的话,因为映射区是在1G地址位置,而且映射区与栈相对生长,malloc申请的空间大于128KB的话,调用的是mmap函数,因此分配的地址起始在1G位置,末端为3G,最大2G左右,所以一次最大申请为2G左右,如果小块小块累计申请的话算上堆区128M到1G区间的话,小块申请 malloc调用brk总和就0.9G,累计能申请到的为2.9G。
    2.6到当前版本的话,因为映射区是在顶端靠近栈区,但是生长方向向下,与堆向上相对,一次malloc申请大空间,malloc调用mmap()能最大申请到2.9G左右,算上堆区128M开始向上小块累计的话,(因为2.9G被mmap了)累计就剩下零头,累计申请最大也是2.9G。
    现在分配的才是虚拟地址(不是物理内存,即使物理内存才0.5G),只有真正使用的话,才会建立页表开始关联物理内存。
    测试代码如下(Linux系统下,物理内存+交换内存>=4G情况下,得到2.8G左右,如果物理内存+交换内存 = N < 4GB, 得到的大概为(N - 0.2)G)
    #include<stdio.h>

    #include<stdlib.h>

    size_t maximum=0;
    int main(int argc,char *argv[])
    {
    void * block;
    void * tmpblock;
    size_t blocksize[]={1024*1024, 1024, 1};
    int i,count;
    for(i=0;i<3;i++){
    for(count=1;;count++){
    block = malloc(maximum+blocksize[i]*count);
    if(block){

    tmpblock = block;
    maximum += blocksize[i]*count;
    free(block);
    }else{
    break;
    }
    }
    }
    printf("maximum malloc size = %lf GB ",maximum*1.0 / 1024.0 / 1024.0 / 1024.0);
    printf("the address is %x ",tmpblock);
    printf("the address end is %x ", tmpblock + maximum);
    while(1);
    }
    著作权归作者所有。
    商业转载请联系作者获得授权,非商业转载请注明出处。
    作者:Cascade
    链接:http://www.zhihu.com/question/20836462/answer/16341442
    来源:知乎

    地址空间限制是有的,但是malloc通常情况下申请到的空间达不到地址空间上限。

    内存碎片会影响到你“一次”申请到的最大内存空间。比如你有10M空间,申请两次2M,一次1M,一次5M没有问题。但如果你申请两次2M,一次4M,一次1M,释放4M,那么剩下的空间虽然够5M,但是由于已经不是连续的内存区域,malloc也会失败。

    系统也会限制你的程序使用malloc申请到的最大内存。Windows下32位程序如果单纯看地址空间能有4G左右的内存可用,不过实际上系统会把其中2G的地址留给内核使用,所以你的程序最大能用2G的内存。除去其他开销,你能用malloc申请到的内存只有1.9G左右。

    理论上这个空间能达到系统给分配的线性空间最大值,而和具体的内存实际大小没有关系。比如32位下windows大概2g,而Linux3G,其余的都是给了内核。
    malloc的机制是:分配时先从进程线性地址空间分配一块线性地址返回给用户进程,直到你读写这块地址才触发真正的缺页请求,从内存申请真正的内存块给用户。也就是说你请求了比如100M,但你只用过一次这块内存50k,那么实际上内核真正给你用的可能很就是128k,内存伙伴算法。
     
     
  • 相关阅读:
    搭建VirtoCommerce2.6开发环境,同官方dev分支保持同步(上)
    VirtoCommerce中文博客站,2015年11月18日上线了!
    C#编程连接数据库,通过更改配置文件切换数据库功能。
    浅谈dataGridView使用,以及画面布局使用属性,对datagridview进行增删改查操作,以及委托使用技巧
    将listBox中信息显示在dataGridview中,操作datagridview后删除listBox信息和SQL数据库信息 续(浅谈listBox..)
    for语句嵌套使用 实现9*9乘法表
    浅谈ListBox控件,将对象封装在listBox中,在ListBox中显示对象中某个属性,在ListBox中移除和移动信息
    使用SignalR为FineUI/Webform打造消息总线
    封装一个错误重试类
    封装一个锁处理类
  • 原文地址:https://www.cnblogs.com/timssd/p/5024873.html
Copyright © 2011-2022 走看看