| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 964 人关注过本帖, 1 人收藏
标题:動態分配内存malloc()的一些測試結果
只看楼主 加入收藏
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
结帖率:100%
收藏(1)
已结贴  问题点数:100 回复次数:18 
動態分配内存malloc()的一些測試結果
C語言的動態分配内存,使用malloc()函數(在stdlib或malloc頭中),它在堆内存中申請一塊指定大小size(字節計數)的空間,可能有人以爲size是多少,就佔用了多少堆空間,下面就是關於這個問題的測試。

malloc()函數是返回分配空間入口地址的,測試的原理如下:連續申請兩塊空間,看兩者的入口地址差是多少,即知實際佔用的内存是否等於所申請的尺寸。代碼如下:
程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

void Pause(const char* message = "\nPress any key to continue...");

int main(void)
{
    // 這裏不作任何別的動作,緊鄰申請兩塊空間,理論上它們是連續的
    char* p1 = (char*)malloc(1000);
    char* p2 = (char*)malloc(1000);

    // 查看兩塊空間的入口地址差,p2 - p1的結果,就是p1所佔用的堆空間
    printf_s("p2 - p1 = %d\n", p2 - p1);

    Pause();
    return EXIT_SUCCESS;
}

void Pause(const char* message)
{
    printf_s(message);
    _getch();
}


運行結果如下:
图片附件: 游客没有浏览图片的权限,请 登录注册


這個結果,我們可得到如下結論:
1.malloc()申請實際所佔用的堆内存,可能是不等於申請尺寸的,如圖示,申請1000字節的内存,實際上分配了1024字節。這與幫助文檔中所描述的一致:
The malloc function allocates a memory block of at least size bytes. The block may be larger than size bytes because of the space that's required for alignment and maintenance information.

2.修改測試數據,把第一個malloc()的參數改爲10,結果爲9992(比申請的10大得多),并非負數,這表明我們根本不能假定兩塊空間的先後次序。事實上,到50才出現負值結果,這中間不管size是多少,都是9992。所以,我們不要自作聰明,以爲後申請的在後,或在前,甚至,我們連實際上佔用了多少都不能假定,因爲這極可能與平臺有關。平常見不少人,用malloc()申請一個int之類,以爲節省了多少空間,殊不知浪費了多少,這還不說你用遠指針間接訪問的低效了(那些用指針存取基本數據類型的尤其如此)。指針和動態分配内存不是那般用的。



[ 本帖最后由 TonyDeng 于 2015-2-14 10:44 编辑 ]
2015-02-14 02:01
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
收藏
得分:25 
学习了。但不能苟同TonyDeng版主观点。
我的代码:
void main()
{
    char *p1,*p2;
    p1=(char*)malloc(980);
    p2=(char*)malloc(10);
    printf("%d\n",p2-p1);
    free(p1);
    free(p2);
}
p1申请的空间大小从1至980时,p2-p1均为-64,当p1申请的空间大于980后,p2-p1为4180544。仔细百度了下关于堆的知识,发现申请堆地址的大小和申请先后的关系不大,不一定紧挨着。
百度内容:堆分配和系统有关,当系统收到程序的堆申请时,会遍历空闲内存地址的链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。堆内存是向高地址扩展的数据结构,是不连续的内存区域。可见申请堆空间没有浪费,我用vc6调试时,觉得申请的空间大小=size+4,并且申请的空间初始化为0xcd(-51),后面4字节初始化为0xfd(-3)。

能编个毛线衣吗?
2015-02-14 06:31
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
我沒看出你不同意我什麽。

授人以渔,不授人以鱼。
2015-02-14 09:41
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
在物理内存堆上用鏈式分配空間,是DOS時代的方式,NT之後,堆在邏輯内存上,這叫“虛擬内存”。我前面說了,這些東西跟平臺有關,不要去做假定,以爲是如何的,實際上并不是,所以編程不要總去鑽系統實現的細節,比如假定int是多少字節、内存必定是連續的之類。理論上,兩次連續申請的空間,如果中間沒有任何別的操作,那麽被斷開的可能性并不大,這從上述代碼反復執行的結果不變可知——如果是物理堆,多任務系統隨時會佔用内存,那麽不同的執行結果應是不同的居多,但事實是每次都是同樣的結果。

在棧上連續分配兩個數組,我們經常見到前一個數組溢出蔓延到下一個數組的現象,即這兩個數組是連續的,但如果在兩個數組定義的中間插入一個別的變量,則會被這個變量分隔。在堆上,理論上也如此,這就是我前面測試代碼强調緊鄰申請的原因。


[ 本帖最后由 TonyDeng 于 2015-2-14 10:40 编辑 ]

授人以渔,不授人以鱼。
2015-02-14 10:01
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
看點資料:
图片附件: 游客没有浏览图片的权限,请 登录注册


源自《Windows核心編程》(第五版)

授人以渔,不授人以鱼。
2015-02-14 10:38
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:25 
分配好像是以4K为单位的
2015-02-14 10:40
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
其實這也是内存對齊的問題,不同的機器、不同的系統有不同的方式,精通那些并不會使我們編程更牛。按照規範,以人類邏輯編程就好了,總是思考機器的問題,沒必要,除非你就是做機器的。

授人以渔,不授人以鱼。
2015-02-14 10:52
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
收藏
得分:0 
回复 3楼 TonyDeng
怪我表述不清,我不苟同的是:
1、你用两个连续的空间申请不能说明地址连续,更不能用两个空间首地址相减来表示第一个空间实际大小。
2、百度表述系统会把多余出来的空间描述为空闲,基本上程序申请多少就给多少,不会浪费。当然到虚拟内存后会造成分页浪费(分页大小取决于系统,一般4096)

能编个毛线衣吗?
2015-02-14 11:00
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
可能你和那個百度作者寫的内存管理程序才會用鏈表形式搜尋空隙分配内存,還要多少分多少呢。

授人以渔,不授人以鱼。
2015-02-14 11:14
tlliqi
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:204
帖 子:15453
专家分:65956
注 册:2006-4-27
收藏
得分:25 
不懂 接分
2015-02-14 11:38
快速回复:動態分配内存malloc()的一些測試結果
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017388 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved