注册 登录
编程论坛 C++教室

为什么malloc使用的空间远远大于实际申请的空间?

vfdff 发布于 2010-08-08 10:38, 1437 次点击
程序代码:
// 目的:malloc 函数实现方式探索
// 平台:VC6.0 20100815

#include   <stdio.h>

#include   <stdlib.h>
#include   <malloc.h>
#include   <assert.h>

char *Alloc_CHAR_Array(long length)
{
    char *array = NULL;
   

    if( NULL == (array = (char *)malloc(sizeof(char) * length) ) )
    {
        fprintf(stdout, "Merory Exhausted\n");
        return NULL;
    }
    //memset(array, 0, length*sizeof(double));
    return array;
}

void Free_Array (char **array)
{   

    assert( array != NULL);
    printf("array=0x%p,*array=0x%p\n",array,*array);
    free(*array);
}

int main()

{

    char *p1 = Alloc_CHAR_Array(0x100);
    char *p2 = Alloc_CHAR_Array(0x100);
    printf("p1=0x%p,p2=0x%p\n",p1,p2);
    p1[0] = '1';
    p2[0] = '2';

    // 验证 Free_Array 正确的释放了空间
    Free_Array(&p1);
    p1 = Alloc_CHAR_Array(0x100);
    p1[0] = '1';

    p2[0] = '2';
    printf("p1=0x%p,p2=0x%p\n",p1,p2);
   

    //

    Free_Array(&p2);
    p2 = Alloc_CHAR_Array(0x90);

    printf("p1=0x%p,p2+0x90=0x%p\n",p1,p2+0x90);

    char *p3 = Alloc_CHAR_Array(0x10);
    printf("p1=0x%p,p2=0x%p,p3=0x%p\n",p1,p2,p3);

    printf("p1=0x%p,p3+0x10=0x%p\n",p1,p3+0x10);
    p3 = Alloc_CHAR_Array(0x10);
    printf("p1=0x%p,p2=0x%p,p3=0x%p\n",p1,p2,p3);
   

    return 0;
}

发现实际申请的 0x10 字节空间,在malloc申请时总被占用0x38 个字节的存储空间!
只有本站会员才能查看附件,请 登录
7 回复
#2
yxwsbobo2010-08-08 11:30
没有被占用   malloc 申请内存并不能保证所申请的内存是连续的
#3
vfdff2010-08-08 11:49
是的,但总是0x38 你不觉得很奇怪?
这中间空着的干什么用呢 ?
#4
yxwsbobo2010-08-08 14:48
考虑这个问题没啥意义

我这里看是0x40 在调试状态看又一个数 Release另一个数


非要问为啥的话,那要明白 malloc干了什么  


malloc 在堆上分配内存,他调用 HeapAlloc

堆又是啥

WINDOWS用户模式下最基本的内存分配是 VirtualAlloc (更底层的函数是非文档的zwAllocateVirtualMemory) 这个API分配4KB整数被的内存(以后可能变)
也就是说每次至少分配4KB,所以使用不方便,操作系统为了使用方便,自动的分配管理使用的这块内存,所以就有了堆,可以在堆上分配 4字节long而不必担心其余内存会浪费

也就是说 malloc 把一块很大的内存中的一个地址给你,这个地址在哪是他内部的实现,他有自己的算法决定在哪里开始分配内存
#5
vfdff2010-08-08 15:12
回复 4楼 yxwsbobo
是的,对于使用者是不用关心这个问题的
但是我想在嵌入式系统上实现自己的malloc函数,借鉴下操作系统的做法的话,还是要深究下这个函数到底怎么实现的
#6
东海一鱼2010-08-08 17:20
堆管理算法比较复杂的,所以很多编译器厂商为了展示自己编译工具的优点,都对其有很深入的研究。
他们一般不使用操作系统提供的堆管理器,而只用系统提供的虚拟内存管理来分配大块的内存数据。
采用自己的堆管理算法来管理小的内存对象,声称这样可以提供更高效的管理、执行效能。

就像你自己设计一个数据对象管理系统,除了数据本身。你自己用来管理数据的数据结构对象是否也要
占用一些内存空间哪?


[ 本帖最后由 东海一鱼 于 2010-8-8 17:26 编辑 ]
#7
vfdff2010-08-08 20:20
恩,看来要重算法上仔细研究才是王道!
#8
pangding2010-08-09 00:17
如果你想做嵌入式的话,是不是应该考虑一下硬件的特性?

操作系统一般现在普遍使用分页机制是因为硬件对这些功能直接提供支持。比如按 4KB 分,就是因为 Intel 体系中一页就是这么大。
虚拟内存的使用也是操作系统的一个重要课题,现代操作系统都支持这种技术。

不过如果你要自己做的话,有时还要在复杂性上做权衡,没必要引入复杂度时,应该避免。比如做非多任务的系统时,可以独占内存,那就没必要这么麻烦。

malloc 一般来说不一定是向系统申请内存。系统一般是——由于有虚拟内存,所以每个进程可以占用全部的虚拟内存,然后操作系统再用分页机制映射到物理内存里——把高地址的内存拨给你并记录你能用到的最低点,你若不够,系统就把你能用的内存区的最低点往下降,使你获得更多的内存。你用不到的内存映射到了非法的物理地址上,你要用的就按页分配。malloc 的任务是负责盘查能用的内存区里还有没有足够的空间,如果有就直接返给程序,如果没有,就尽可能少的让系统把最低点往下降。然后自己组织好了,再返给程序。用 free 时,内存其实只是还给了 malloc 管理的空间上,没有返给操作系统。一般来说没有简单的方法能把内存还给操作系统,因为这会给操作系统带来太大的負担。malloc 一般用链表的方式管理空闲的内存,可能也结合一定的索引方法,不同的实现算法具体上会有差别。
1