如题,然后下面是一个朋友给我的解答:
1)C库老老实实地待在硬盘里,没法管这事。free()是库函数,没错。可这就给许多人错觉,以为,C自己把这事给办了。空间回收和空间分配一样,涉及到两块空间:虚拟空间与物理空间。虚拟空间是进程私有的,这没事,进程可以自行了断。但物理空间一共就一块,所有的进程都共用它。如果让每个进程自行做垃圾回收,那不就乱了套了?因此,我想象,库函数free()只是通知“可以回收啦”而没有真正回收空间。
2)当虚存释放空间时,如果系统立即做实存的回收,那会把系统累死。整个系统的运作效率大大降低。因此,现代系统的垃圾回收都有一些算法。这个好比你家门口的垃圾袋,并不是你放出去,小区清洁工立即拿走的。没有一个清洁工能对小区所有业主做到这样的服务,除非她是超人或机器猫。如果系统足够聪明,能识别某进程已经僵死并回收了它所占的空间,那为啥还剩下它的PCB呢?
但是还是不太懂,而且这个不一定是唯一答案,有这方面专业的大神来解答下吗?
1
tonyluj 2015-03-29 17:01:07 +08:00
如果是Linux,可以参考 深入理解Linux内核,Slab和伙伴分配算法。
|
2
wind3110991 OP 能不能理解为:
free 告诉的是 C 库,在一般的 OS 上,malloc/free 都不是 system call,而是库函数。这些空间释放不释放,是 C 库说了算,还没到 OS |
3
hjc4869 2015-03-29 17:03:12 +08:00 via iPhone
楼主先研究一下HeapAlloc和HeapFree。另外C库本身可能有很多种实现,单纯研究malloc是什么都没有的。
|
5
choury 2015-03-29 17:13:23 +08:00
在linux下面实现的实现你可以参考下brk和sbrk这两个系统调用,一般free的内存是不会让操作系统收回的
|
6
damngood 2015-03-29 18:02:43 +08:00
可以直接看看 c 库的源码. 应该不同的 c 库实现的原理不会差太多. 所以可以找个小点的 c 库, 比如 musl lib c 来看一会儿也就差不多了解了.
我记得 musl lib 里 free 的时候最后是调的是 madvise syscall 来的? |
7
fenjuly 2015-03-29 18:26:01 +08:00 1
我猜楼主去参加了腾讯的笔试
|
8
XiaoxiaoPu 2015-03-29 18:32:54 +08:00
《深入理解计算机系统》,第 9 章虚拟存储器,楼主看了就懂了。
|
9
DiveIntoEyes 2015-03-29 19:15:34 +08:00 3
|
10
wind3110991 OP @fenjuly 不错啊,这个问题之前还真没仔细想下,看了下free函数的源代码
|
11
wind3110991 OP @wzxjohn 意思是我是人类就不能用动物做头像了?
|
12
wy315700 2015-03-29 19:39:03 +08:00
内存分配和释放那是C库的事情,
操作系统只管内存分页映射的事情,你内存怎么用他不管 |
13
kn007 2015-03-29 19:58:34 +08:00
|
14
wwqgtxx 2015-03-29 20:03:38 +08:00 via Android
@wind3110991 这个是L大的规定,就是不准男生用女生的头像,所以(≧∇≦)
|
15
albert43 2015-03-29 20:24:00 +08:00
貌似是今天腾讯的笔试题啊,不过我没去,楼主广研那边一面之后就没消息了么?
|
16
wzxjohn 2015-03-29 20:29:09 +08:00
|
17
nicai000 2015-03-29 20:36:59 +08:00
这题的答案是不会.
但当然不能这么肯定, 你可以自己写个操作系统和C库, 就马上回收, 咋咋地? |
18
jonah 2015-03-29 22:16:52 +08:00 via iPhone 1
不会,比如C库申请了一大块内存,中间的一块释放了,而高地址有一块没释放,那么中间那块就不会还给操作系统,但用户代码申请新内存时那块还能用。
|
19
wind3110991 OP @albert43 没了 - -目测被刷了
|
20
Monad 2015-03-29 22:46:32 +08:00
Google "ptmalloc2" "tcmalloc" "jemalloc" 看完源代码就懂了~
就我自己的感受来说,tcmalloc最清晰,glibc里面的ptmalloc2次之, jemalloc简直… |
21
wind3110991 OP @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库无法在物理内存层面对内存进行直接管理 但是始终有些困惑= =感觉半懂半懵, 我还是再研究下 |
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 |
23
bcxx 2015-03-29 23:28:07 +08:00 1
|
24
wind3110991 OP @bcxx 大神!!那么请问下如果在同一个编译模块下,我在free了一块内存(我叫他为Page1)后再次malloc,那么之前os会有可能分配之前申请到的那一块相同的内存(Page1)吗?是不是free后被标记就暂时无法再被分配了
|
25
Andiry 2015-03-30 00:03:39 +08:00
@wind3110991 当然可能,而且应该如此,减少page fault
|
26
wind3110991 OP @Andiry 谢谢!
|
27
wind3110991 OP @tonyluj 感觉内核代码还不适合我研究啊,现在刚刚入门
|
28
wind3110991 OP @fenjuly bingo~
|
29
hyuwang 2015-03-30 02:38:55 +08:00
mark下 还挺好奇的
写C的时候是直接malloc完乖乖free没有想很多 编MIPS的的时候对stack的操作是即时的,用完即pop,不知道可不可以类推到C |
30
qq446015875 2015-03-30 13:34:21 +08:00 via Android
@DiveIntoEyes thanks!我看了下你发的链接,写的很清楚啊
|
31
chisato 141 天前
虚拟内存,可以一直分配,但是物理内存不会超过一定限制的。
|