问一下,free的实现机制

cfvmario 2011-10-26 03:59:53
c++里
int *a;
a = new int[10];
delete a[];
我们告诉编译器要释放的是一个数组,这没问题
可是c里
int *a;
a = (int*)malloc(10*sizeof(int));
free(a);
问题来了,要是按字面意思,这会内存泄漏啊,free(a)由于a是个int*,只释放一个int的空间,另9个int都会丢失才对
当然编译器让它不泄漏是好事,但是就是不知道这内部是怎么做到的,写这样的代码总觉得不踏实
ps: 现在用c,好久不用c++都忘了。。在这个例子里int是内部类型,是不是写delete a;也没事?是不是只有class类型的东西才需要使用delete [];来显式指定要释放的是一个数组?
...全文
223 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
AndyZhang 2011-10-27
  • 打赏
  • 举报
回复
告诉系统这段内存可以用了,但是里面的东西不一定会清空
proorck6 2011-10-26
  • 打赏
  • 举报
回复
空闲空间有个循环链表,我就知道这些。
cgl_lgs 2011-10-26
  • 打赏
  • 举报
回复
你根本碰不到操作系统层面,操作系统是给进程一个新的空间,然后把内存信息存到一个只有0级权限(操作系统就有)才能修改的地方,你再怎样破坏也只是破坏了自己当前进程的信息。而当你这个进程结束时,系统会回收你所有申请的东西。

所以你修改malloc的头信息只是破坏了程序内部空间,外部是不会乱的:)
cfvmario 2011-10-26
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 maquan 的回复:]

无论 C 还是 C++,分配内存和释放内存都是针对一个“内存块”,而不管你在那个内存块上放了多少个“数据对象”。

所以,C 里面 free(a) 不会泄漏什么内存。

C++ 里 delete a[] 的写法其意义在于,在释放内存之前,先针对这块内存上的每个“数据对象”进行析构(如果是需要析构的数据对象的话)。在楼主的这个具体的例子里,delete a[] 与 delete a 是等价……
[/Quote]
这么理解是否正确:
1、也就是说,free(a)与a是什么类型的指针无关,就是说,a是malloc分出来的块的数据区地址,只管释放。或者说准确的写法应该是free((void*)a),只不过void*不必指出来。

2、int *a唯一的目的是,告诉编译器,通过a(及其与整数的加减法)取得的是一个int。而a[i]不过是语法糖,当做*(a+i)理解,编译器是根本不知道a是否是一个数组的,它只管照*(a+i)解释。
int i;
int *a=&i;
a[0]=... //合法,仍然是对i赋值

3、那么,“指针=地址”这个说法就已经有问题了。当你写int i; int *a=&i;的时候,指针就是地址。但是,malloc返回的东西,和free的参数,就不是地址这么简单,应该说是——操作系统所分配出的内存块的数据区的地址。这里就得强调数据区,因为操作系统总得有办法知道它的长度。拿C的语法来说,操作系统定义了个这东西:
struct {
unsigned int size;
void *data;
} __Memory_Block;
当调用malloc时,操作系统分配了个__Memory_Block,但是返回值是data。那么,如果data未动,而size却被破坏了,就无法正确释放。理论上说,可以在a的周围越界写一些东西破坏掉内存块相关信息,使free失效甚至崩溃。这个说法对么?
int i;
int *a=&i;
free(a); //操作系统会试图将a当做data,找size的位置,这个位置数据不正确,崩溃

int *a=(int*)malloc(10*sizeof(int));
*(a-1)=5; // 破坏size数据?
free(a); // 只释放了5个?

4、操作系统是否会将size放在受保护的或只读的内存区域,使得这样的破坏行为不会拖到free时才引发难以捕捉的程序逻辑错误?
cgl_lgs 2011-10-26
  • 打赏
  • 举报
回复
C仅提供了free一种方式来释放内存。
而C++则提供了delete和delete[]。

目的很明确,当初C++提案有人提出:数组属于大内存应用,它不应和小内存应用使用同一个接口,否则不便于更好的进行内存管理。

而对于实现,不同编译器的实现方式是不同的。比如你如果用VC,那么new[]和new分配的内存,都可以用delete释放而不会泄漏。但C++Builder则不可以,如果你用new[]分配的内存直接使用delete的话,那将会导致内存泄漏。

一般地,为了避免频繁分配和释放内存导致调用系统API过多,使得程序性能大大降低。不同runtime实现商都会采取一些轻量化的内存管理措施,比如向系统申请分配内存时以块为单位,但内部使用时则是完全透明的:)这样你在调用new或是malloc时,则runtime库会先看看有没有足够的,已经跟系统要到的内存,如果有,则给你直接返回一个空间(但空间前面会留几个字节做为管理之用)。

我们可以猜想一下,对于分配和释放这样的操作,需要用到什么信息:
长度:如果不考虑调用析构函数,那么这几乎是唯一的;
单元个数:如果是申请一批,并需要调用析构,则这个也需要!

既然长度是必须的,我们自然会这样安排:
[单元个数][长度][数据开始]
实际上你的指针指向的也正是[数据开始]这部分:)

而“长度”是一个很模糊的东西,我可以认为它是单元长度,也可以认为它是总长度。而这样也就解释了为何有些编译器用delete可以在一定情况下替代delete[],而有些则不行:)

当然,如果我们要是还考虑调试的话,前面还需要再增加些东西,比如:分配时的函数栈信息等:)
再如果我们要考虑RTTI的话,可能还需要再带上类型信息……

最后,如果真有兴趣的话,可以在实际当中去看看VC、CB、gcc等runtime库的源码,看看它们到底是如何去做的:)或许会有新的发现呢:)
HONGSEDAIMA1 2011-10-26
  • 打赏
  • 举报
回复
1楼说的是原理。 细节怎么做, 那确实是操作系统的事情。
反正, free()的下面的代码应该用的Heap*来做的。
而Heap*函数是用Virtual*来做的。
而Virtual*是怎么做的, 你去问微软去, 要不你也可以反汇编看看。
maquan 2011-10-26
  • 打赏
  • 举报
回复
无论 C 还是 C++,分配内存和释放内存都是针对一个“内存块”,而不管你在那个内存块上放了多少个“数据对象”。

所以,C 里面 free(a) 不会泄漏什么内存。

C++ 里 delete a[] 的写法其意义在于,在释放内存之前,先针对这块内存上的每个“数据对象”进行析构(如果是需要析构的数据对象的话)。在楼主的这个具体的例子里,delete a[] 与 delete a 是等价的。


————————————————————————————————
基于CSDN论坛提供的插件扩展功能,自己做了个签名档工具,分享给大家,欢迎技术交流 :)
dfsdfsdfwedfwef 2011-10-26
  • 打赏
  • 举报
回复
malloc,new 是在堆上分配的 ,内存地址是向高地址扩展的,,操作系统会在分配的内存首地址出记录分配的内存的大小,偏于free,delete释放
majia2011 2011-10-26
  • 打赏
  • 举报
回复
没跟一下new和delete?如果跟了你会时刻不踏实的,呵呵呵

真的应该先学c,再学c++
赵4老师 2011-10-26
  • 打赏
  • 举报
回复
操作系统内存管理模块在malloc时会记住返回给你的指针占用多少个字节,当你free该指针时自然就知道释放多少个字节的内存块了。
恨天低 2011-10-26
  • 打赏
  • 举报
回复
1楼说得有道理。估计是那样吧
queatin_man 2011-10-26
  • 打赏
  • 举报
回复
这个机制好像没那么重要
cfvmario 2011-10-26
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 dx_deepblue 的回复:]
free(a)由于a是个int*,只释放一个int的空间
明明写的是申请了10个,你怎么能说只是一个
[/Quote]
关键是从int* a这里是根本无法知道a是只指向一个int?还是后面有一个分配过的数组?
a = (int*)malloc(sizeof(int));不是也行么?
但是后面却调用的都是同一个free(a),都不指示a是否为一个数组了
vilnies 2011-10-26
  • 打赏
  • 举报
回复
您过滤了,哪您说 new int[100] 的delete是否比new int[10]的delete泄漏90个呢。
DX_deepblue 2011-10-26
  • 打赏
  • 举报
回复
free(a)由于a是个int*,只释放一个int的空间

明明写的是申请了10个,你怎么能说只是一个
suizouwuya 2011-10-26
  • 打赏
  • 举报
回复
c++里面分配数组空间的同时会多出四个字节的空间来存放数组的长度,调用delete[] a编译器就会根据那个长度去释放内存,我估计c中的机制跟这个差不多吧。

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧