关于malloc和realloc的问题

Rtubo 2002-09-24 09:00:06
int *p;
p=(int *)malloc(3*sizeof(int));
free(p);
问题是在free的时候,对于指针p,free怎么知道应该释放多少位内存?
如果是
int *p,*q;
p=(int *)malloc(3*sizeof(int));
q=p;
free(q);
它还能正确的释放吗?
下面是realloc的问题:
int *p;
p=(int *)malloc(3*sizeof(int));
p[0]=100;
p=(int *)realloc(p,4*sizeof(int));
free(p);
1.realloc是不是重新开辟了4个sizeof(int)的内存,把原来的3个sizeof(int)的内容复制过去?也就是说p[0]在执行了realloc后是否还是100?如果重新开辟的小于原来开辟的,是否只复制前面的一部分数据.
2.执行了realloc后,原来的那3个sizeof(int)是不是会自动被释放掉?
望高手详细回答.不胜感激

...全文
548 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
Rtubo 2002-09-26
  • 打赏
  • 举报
回复
多谢各位高手踊跃回答.我也明白了.
chinaeagle 2002-09-25
  • 打赏
  • 举报
回复
nt *p,*q;
p=(int *)malloc(3*sizeof(int));
q=p;
free(q);

p和q是不是指向了同一个内存块啊???
geeksky 2002-09-25
  • 打赏
  • 举报
回复
谢谢各高手纠正我的错误理解

要不可能还有排错呢

谢谢
lbaby 2002-09-25
  • 打赏
  • 举报
回复

恕我直言,geeksky(-=【沉思·幻想】=-) 的大部分回答简直就是误人子弟!

1. 问题是在free的时候,对于指针p,free怎么知道应该释放多少位内存?

【答】每个分配的内存块都有附加的空间纪录其信息(主要是其大小)

2. 如果是
int *p,*q;
p=(int *)malloc(3*sizeof(int));
q=p;
free(q);
它还能正确的释放吗?

【答】能!因为“q=p;”

3.realloc是不是重新开辟了4个sizeof(int)的内存,把原来的3个sizeof(int)的内容复制过去?也就是说p[0]在执行了realloc后是否还是100?如果重新开辟的小于原来开辟的,是否只复制前面的一部分数据.

【答】SURE!你的猜测非常正确!

4.执行了realloc后,原来的那3个sizeof(int)是不是会自动被释放掉?

【答】相当于自动被释放掉。为什么说“相当于”呢?realloc 后的内存起始地址可能与原来相等,也可能是在新的地址。对于后者,就是分配新空间,释放旧空间;对于前者,并没有实际的“分配”“释放”操作,只是修改了原内存块的大小,当作用相当于释放原空间,分配新空间



比较好,学习中
13312933476 2002-09-25
  • 打赏
  • 举报
回复
同意 alexxing(赤铸) 老兄的意见!!!!!!!!!!
_炳叔_ 2002-09-25
  • 打赏
  • 举报
回复
关于第一个问题,有系统自动完成,勿庸你操心。
至于第二个问题,建议不要这么用
p=(int *)realloc(p,4*sizeof(int));
最好是:q=(int*)realloc(p,4*sizeof(int));
if(q==0)
{
.........
}
p=q;

cwanter 2002-09-25
  • 打赏
  • 举报
回复
关于堆内存的管理,转贴一篇文章:

--------------------------------------------------------------------------------


原创:isno(isno)
__________________________________________

二、Windows的HEAP管理机制简述
同LINUX一样,Windows的HEAP区是程序动态分配一块内存区域。程序员一般调用C函数malloc/free或者C++的new/delete或者WIN32 API函数HeapAlloc/HeapFree来动态分配内存,这些函数最终都将调用ntdll.dll中的RtlAllocateHeap/RtlFreeHeap来进行实际的内存分配工作,所以我们只需要分析RtlAllocateHeap/RtlFreeHeap就行了。

对于一个进程来说可以有多个HEAP区,每一个HEAP的首地址以句柄来表示:hHeap,这也就是RtlAllocateHeap的第一个参数。每个HEAP区的整体结构如下:

+-------------------------------------------------------------------+
| HEAP总体管理结构区 | 双指针区 | 用户分配内存区 |
+-------------------------------------------------------------------+
^ ^
|_hHeap |_hHeap+0x178

heap总体管理结构区存放着一些用于HEAP总体管理的结构,这不是我们所关心的。双指针区存放着一些成对出现的指针,用于定位分配内存以及释放内存的位置,这可能是某种树结构,我还没完全搞清楚。用户分配内存区是用户动态分配内存时实际用到区域,也这是HEAP的主体。

当我们调用RtlAllocateHeap(HANDLE hHeap,DWORD dwFlags,SIZE_T dwBytes)来分配内存时将进行以下操作:
对参数进行检查,如果dwBytes过大或小于0都按照出错处理,根据dwFlags来设置一些管理结构;
检查是否为DEBUG程序,对于DEBUG的程序与实际运行的程序每个内存块之间的结构是不同的,所以我们下面说到的都是以RELEASE版编译的实际运行的程序(不是在MSDEV中调试的程序);
根据要分配的内存的大小(dwBytes)决定不同的内存分配算法,我们只分析小于1024 bytes的情况;
从双指针区找到用户内存区的末尾位置,如果有足够的空间分配所需的内存,就在末尾+dwBytes+8的位置放置一对指针来指向双指针区的指向用户内存区末尾位置的地方;
在后面同时设置双指针区的指向用户内存区末尾位置的指针指向进行完分配之后的用户内存区末尾位置。这么说可能有点绕,不过这跟HEAP溢出没有太大的关系,所以我们就不细究了。

两块连续分配的内存块之间并不是紧挨着的,而是有8字节的管理结构,最末尾的一块内存后面还另外多了8字节的指针指向双指针区,就是上面提到过的。

假设有以下程序:
buf1 = HeapAlloc(hHeap, 0, 16);
buf2 = HeapAlloc(hHeap, 0, 16);
连续分配了两块16字节内存,实际在内存中(用户分配区)的情况是这样的:

第一次分配后:
+-----------------------------------------------+
| buf1 | 8 byte |4 byte|4 byte|
+-----------------------------------------------+
| 用户内存 | 管理结构 | 两个指针 |

第二次分配后:
+---------------------------------------------------------------------------------+
| buf1 | 8 byte | buf2 | 8 byte |4 byte|4 byte|
+---------------------------------------------------------------------------------+
| 用户内存 | 管理结构 | 用户内存 | 管理结构 | 两个指针 |

在第二次分配内存的时候会利用第一块内存管理结构后面那两个指针进行一些操作,其中会有一次写内存的操作:

77FCB397 mov [ecx], eax
77FCB399 mov [eax+4], ecx

这时的eax和ecx分别指向:
+-----------------------------------------------+
| buf1 | 8 byte |4 byte|4 byte|
+---------------------------------^------^------+
| 用户内存 | 管理结构 |_eax |_ecx |


cwanter 2002-09-25
  • 打赏
  • 举报
回复
geeksky(-=【沉思·幻想】=-) 把指针变量和指针变量指向的内存地址搞混了。p,q是局部变量,它们的值在栈上,它们指向的内存地址在堆上。free函数只是将它们指向的内存地址内容清除。它们所占内存(4个字节)要等到它们的范围结束时被释放。
xdspower 2002-09-25
  • 打赏
  • 举报
回复
gz
sandrowjw 2002-09-25
  • 打赏
  • 举报
回复
前面说错了,标志(就是那个甜饼)的确在所分配的区域前面,realloc如果重新分配的大小不超过预留的空间大小,则原区域增长(方向是向上,不是我原来说的向下),否则就要重新开辟一块区域并free掉现在的那块区域。所有原来的数据都会重新搬移到新的区域里去。
goldsoft 2002-09-25
  • 打赏
  • 举报
回复
int *p;
p=(int *)malloc(3*sizeof(int));
free(p);
问题是在free的时候,对于指针p,free怎么知道应该释放多少位内存?
答:这由系统知道。
如果是
int *p,*q;
p=(int *)malloc(3*sizeof(int));
q=p;
free(q);
它还能正确的释放吗?
答:q=p实际由q指向p的内存区,free(q)已释放了p的内存区,如再free(p)就不对了.
下面是realloc的问题:
int *p;
p=(int *)malloc(3*sizeof(int));
p[0]=100;
p=(int *)realloc(p,4*sizeof(int));
free(p);
1.realloc是不是重新开辟了4个sizeof(int)的内存,把原来的3个sizeof(int)的内容复制过去?也就是说p[0]在执行了realloc后是否还是100?如果重新开辟的小于原来开辟的,是否只复制前面的一部分数据.
2.执行了realloc后,原来的那3个sizeof(int)是不是会自动被释放掉?
望高手详细回答.不胜感激
答:realloc是重新按第2个参数的大小分配内存,如果第二个比原来的大相当于再增加了部分内存,同时保存了在原来内存中的数据。如果小的话那部分数据就掉失了,内存空间为第二个参数指定的大小。

jieshen 2002-09-24
  • 打赏
  • 举报
回复
gz
alexxing 2002-09-24
  • 打赏
  • 举报
回复
恕我直言,geeksky(-=【沉思·幻想】=-) 的大部分回答简直就是误人子弟!

1. 问题是在free的时候,对于指针p,free怎么知道应该释放多少位内存?

【答】每个分配的内存块都有附加的空间纪录其信息(主要是其大小)

2. 如果是
int *p,*q;
p=(int *)malloc(3*sizeof(int));
q=p;
free(q);
它还能正确的释放吗?

【答】能!因为“q=p;”

3.realloc是不是重新开辟了4个sizeof(int)的内存,把原来的3个sizeof(int)的内容复制过去?也就是说p[0]在执行了realloc后是否还是100?如果重新开辟的小于原来开辟的,是否只复制前面的一部分数据.

【答】SURE!你的猜测非常正确!

4.执行了realloc后,原来的那3个sizeof(int)是不是会自动被释放掉?

【答】相当于自动被释放掉。为什么说“相当于”呢?realloc 后的内存起始地址可能与原来相等,也可能是在新的地址。对于后者,就是分配新空间,释放旧空间;对于前者,并没有实际的“分配”“释放”操作,只是修改了原内存块的大小,当作用相当于释放原空间,分配新空间
topikachu 2002-09-24
  • 打赏
  • 举报
回复
re :问题是在free的时候,对于指针p,free怎么知道应该释放多少位内存?
标准没有规定具体方法,由实现自己决定.
一般的编译器是在malloc的变量前面再放一个cookie,记录这次分配的内存大小(见 今年第9期"程序员" 中 侯捷 关于 memory pool的介绍)
sandrowjw 2002-09-24
  • 打赏
  • 举报
回复
to geeksky(-=【沉思·幻想】=-):
4个字节为指针的长度,当然要占用的,q并没有被消除,甚至没有设为NULL,不过是把它指向的那个区域标记了。还有我发觉每次是预留空间的,如果只分配3、4个字节的话,每次实际分配的空间为40个字节,这大概就是类似伙伴系统的算法吧。没有用到的空间是用两个FDFDFDFD一前一后括着,里面还有相关的堆信息。
pi1ot 2002-09-24
  • 打赏
  • 举报
回复
你指的释放是什么?free()的结果只是os把那块内存标记为可用而已,并不更改其内容,就像删除文件一样。
geeksky 2002-09-24
  • 打赏
  • 举报
回复
为什么我在Dev-C++下Debug发现q所占的内存没有释放的???
我是这样实现的
main()
{
int *p,*q;
p=(int*)malloc(1000*sizeof(int));
q=p;
free(q);
}
跟踪结果为q并没有释放,还是占着4个字节呀??而p也没有释放
为什么会这样的??
是编译器的问题吗??
sandrowjw 2002-09-24
  • 打赏
  • 举报
回复
具体标志好象是FDFDFDFD000000000000000041000000,这是在VC下的数据,各种编译器可能不一样。
sandrowjw 2002-09-24
  • 打赏
  • 举报
回复
观察了VC编译器,发觉是一个trick,实际上malloc()了一段内存后(假设是sizeof(int)*3),内存中是这样的:
CD CD CD CD CD CD CD CD CD CD CD CD FD FD FD FD
前12个字节是CD,就是被分配的内存,最后有四个字节的FD,表示内存块的结束,在释放的时候就以此为标志,所以1、2的结论都是可以准确释放的。
geeksky 2002-09-24
  • 打赏
  • 举报
回复
第一个问题看错了,free根本不知道要释放多少内存,只是把p所指向的区域清0

第三个问题详细点应该是你在没有free掉p就再分配的,会令p原来的内存区域不能释放,以致内存泄漏
加载更多回复(2)

69,371

社区成员

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

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