V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wind3110991
V2EX  ›  C

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

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

    如题,然后下面是一个朋友给我的解答:
    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!=memptr);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  
       141 天前
    虚拟内存,可以一直分配,但是物理内存不会超过一定限制的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1520 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 17:14 · PVG 01:14 · LAX 09:14 · JFK 12:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.