问一个底层问题, malloc 申请得到的内存后,再 free 释放它的时候,操作系统会立即收回那块内存吗?? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wind3110991
V2EX    C

问一个底层问题, malloc 申请得到的内存后,再 free 释放它的时候,操作系统会立即收回那块内存吗??

  •  1
     
  •   wind3110991 2015-03-29 16:55:24 +08:00 5405 次点击
    这是一个创建于 3902 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,然后下面是一个朋友给我的解答:
    1)C库老老实实地待在硬盘里,没法管这事。free()是库函数,没错。可这就给许多人错觉,以为,C自己把这事给办了。空间回收和空间分配一样,涉及到两空间:虚拟空间与物理空间。虚拟空间是进程私有的,这没事,进程可以自行了断。但物理空间一共就一块,所有的进程都共用它。如果让每个进程自行做垃圾回收,那不就乱了套了?因此,我想象,库函数free()只是通知“可以回收啦”而没有真正回收空间。
    2)当虚存释放空间时,如果系统立即做实存的回收,那会把系统累死。整个系统的运作效率大大降低。因此,现代系统的垃圾回收都有一些算法。这个好比你家门口的垃圾袋,并不是你放出去,小区清洁工立即拿走的。没有一个清洁工能对小区所有业主做到这样的服务,除非她是超人或机器猫。如果系统足够聪明,能识别某进程已经僵死并回收了它所占的空间,那为啥还剩下它的PCB呢?

    但是还是不太懂,而且这个不一定是唯一答案,有这方面专业的大神来解答下吗?

    31 条回复    2024-07-12 13:27:21 +08:00
    tonyluj
        1
    tonyluj  
       2015-03-29 17:01:07 +08:00
    如果是Linux,可以参考 深入理解Linux内核,Slab和伙伴分配算法。
    wind3110991
        2
    wind3110991  
    OP
       2015-03-29 17:01:42 +08:00
    能不能理解为:
    free 告诉的是 C 库,在一般的 OS 上,malloc/free 都不是 system call,而是库函数。这些空间释放不释放,是 C 库说了算,还没到 OS
    hjc4869
        3
    hjc4869  
       2015-03-29 17:03:12 +08:00 via iPhone
    楼主先研究一下HeapAlloc和HeapFree。另外C库本身可能有很多种实现,单纯研究malloc是什么都没有的。
    wzxjohn
        4
    wzxjohn  
       2015-03-29 17:06:02 +08:00
    @Livid 男性使用女性头像。。。
    choury
        5
    choury  
       2015-03-29 17:13:23 +08:00
    在linux下面实现的实现你可以参考下brk和sbrk这两个系统调用,一般free的内存是不会让操作系统收回的
    damngood
        6
    damngood  
       2015-03-29 18:02:43 +08:00
    可以直接看看 c 库的源码. 应该不同的 c 库实现的原理不会差太多. 所以可以找个小点的 c 库, 比如 musl lib c 来看一会儿也就差不多了解了.

    我记得 musl lib 里 free 的时候最后是调的是 madvise syscall 来的?
    fenjuly
        7
    fenjuly  
       2015-03-29 18:26:01 +08:00   1
    我猜楼主去参加了腾讯的笔试
    XiaoxiaoPu
        8
    XiaoxiaoPu  
       2015-03-29 18:32:54 +08:00
    《深入理解计算机系统》,第 9 章虚拟存储器,楼主看了就懂了。
    DiveIntoEyes
        9
    DiveIntoEyes  
       2015-03-29 19:15:34 +08:00   3
    wind3110991
        10
    wind3110991  
    OP
       2015-03-29 19:37:07 +08:00
    @fenjuly 不错啊,这个问题之前还真没仔细想下,看了下free函数的源代码
    wind3110991
        11
    wind3110991  
    OP
       2015-03-29 19:38:24 +08:00
    @wzxjohn 意思是我是人类就不能用动物做头像了?
    wy315700
        12
    wy315700  
       2015-03-29 19:39:03 +08:00
    内存分配和释放那是C库的事情,

    操作系统只管内存分页映射的事情,你内存怎么用他不管
    kn007
        13
    kn007  
       2015-03-29 19:58:34 +08:00
    wwqgtxx
        14
    wwqgtxx  
       2015-03-29 20:03:38 +08:00 via Android
    @wind3110991 这个是L大的规定,就是不准男生用女生的头像,所以()
    albert43
        15
    albert43  
       2015-03-29 20:24:00 +08:00
    貌似是今天腾讯的笔试题啊,不过我没去,楼主广研那边一面之后就没消息了么?
    wzxjohn
        16
    wzxjohn  
       2015-03-29 20:29:09 +08:00
    nicai000
        17
    nicai000  
       2015-03-29 20:36:59 +08:00
    这题的答案是不会.

    但当然不能这么肯定, 你可以自己写个操作系统和C库, 就马上回收, 咋咋地?
    jonah
        18
    jonah  
       2015-03-29 22:16:52 +08:00 via iPhone   1
    不会,比如C库申请了一大块内存,中间的一块释放了,而高地址有一块没释放,那么中间那块就不会还给操作系统,但用户代码申请新内存时那块还能用。
    wind3110991
        19
    wind3110991  
    OP
       2015-03-29 22:41:59 +08:00
    @albert43 没了 - -目测被刷了
    Monad
        20
    Monad  
       2015-03-29 22:46:32 +08:00
    Google "ptmalloc2" "tcmalloc" "jemalloc" 看完源代码就懂了~
    就我自己的感受来说,tcmalloc最清晰,glibc里面的ptmalloc2次之, jemalloc简直…
    wind3110991
        21
    wind3110991  
    OP
       2015-03-29 23:18:11 +08:00
    @jonah

    结合自己写了段测试程序:
    #include<stdio.h>
    int main(){
    unsigned char *p = (unsigned char*)malloc(4*sizeof(unsigned char));
    memset(p,0,4);
    strcpy((char*)p,"Hello guys! ");
    printf("%s",p);
    free(p);
    printf("%s",p);
    return 0;
    }

    输出时打印了两次p的字符串

    然后google了c库里free的源码:

    void free(void* ap)
    {
    Header *bp,*p,*prev;
    bp=(Header*)ap-1;
    for(prev=memptr,p=memptr->s.next;
    (p!=bp) && (p!=memtr);prev=p,p=p->next);
    if(p!=bp) return;
    prev->s.freesize+=p->s.usedsize+p->s.freesize;
    prev->s.next=p->s.next;
    memptr=prev;
    }

    应该按理来说就是这个意思,os涉及物理储存的部分,c函数库是无法进行操作的,申请一块内存后,在进程结束前,c库无法在物理内存层面对内存进行直接管理
    但是始终有些困惑= =感觉半懂半懵, 我还是再研究下
    HowardMei
        22
    HowardMei  
       2015-03-29 23:20:34 +08:00   1
    记忆可能不准,仅供参考:

    Stack由OS统一管理自动分配[地址有序],Heap比较宽松自主管理[地址乱序]

    不同语言对Stack/Heap使用不一样,不过基本上malloc都通过OS来操作,而free却未必会把
    空间直接还给OS,也许只是按特定方式收集标记起来,适时一起归还,也许直接就归还了,
    因为OS对内存管理是按照Page为单位的,你如果要归还的空间不满一个Page,OS无法处理。

    具体到C语言,也是一样,要看库怎么写的,但有OS的情况下,malloc最小申请一个Page,
    而free也通常不会直接释放,而是收集标记后再交给malloc归还给OS
    bcxx
        23
    bcxx  
       2015-03-29 23:28:07 +08:00   1
    wind3110991
        24
    wind3110991  
    OP
       2015-03-29 23:46:53 +08:00
    @bcxx 大神!!那么请问下如果在同一个编译模块下,我在free了一块内存(我叫他为Page1)后再次malloc,那么之前os会有可能分配之前申请到的那一块相同的内存(Page1)吗?是不是free后被标记就暂时无法再被分配了
    Andiry
        25
    Andiry  
       2015-03-30 00:03:39 +08:00
    @wind3110991 当然可能,而且应该如此,减少page fault
    wind3110991
        26
    wind3110991  
    OP
       2015-03-30 00:34:05 +08:00
    @Andiry 谢谢!
    wind3110991
        27
    wind3110991  
    OP
       2015-03-30 00:34:39 +08:00
    @tonyluj 感觉内核代码还不适合我研究啊,现在刚刚入门
    wind3110991
        28
    wind3110991  
    OP
       2015-03-30 00:34:50 +08:00
    @fenjuly bingo~
    hyuwang
        29
    hyuwang  
       2015-03-30 02:38:55 +08:00
    mark下 还挺好奇的
    写C的时候是直接malloc完乖乖free没有想很多
    编MIPS的的时候对stack的操作是即时的,用完即pop,不知道可不可以类推到C
    qq446015875
        30
    qq446015875  
       2015-03-30 13:34:21 +08:00 via Android
    @DiveIntoEyes thanks!我看了下你发的链接,写的很清楚啊
    chisato
        31
    chisato  
       2024-07-12 13:27:21 +08:00
    虚拟内存,可以一直分配,但是物理内存不会超过一定限制的。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2546 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 15:35 PVG 23:35 LAX 07:35 JFK 10:35
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86