回 帖 发 新 帖 刷新版面

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

[code=c]
// 目的: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;

[/code]

发现实际申请的 0x10 字节空间,在malloc申请时总被占用0x38 个字节的存储空间?!

回复列表 (共7个回复)

沙发

首先,楼主给出的这段代码并不能说明什么。malloc可以返回任何可用的内存地址,这些地址可能是不相邻的。单单凭借几个地址之间的距离,不能说明任何问题。
然后,确实每次malloc都会额外的多分配一些空间。往往,这个额外的空间的大小是固定的,因此如果分配很多细小的空间,就会浪费大量的内存,而如果分配一些较大的空间,则基本不会浪费内存。

楼主可以看看这里,这个帖子的楼主,申请了4M的空间,但实际上内存消耗了80M左右。注意我在3楼的回帖。
http://bbs.pfan.cn/post-345682.html

板凳


按照您的说法,系统记录时花费的字节数是不变的,因此我们这里多余的空间是做记录的

但是这样有个问题,就是记录信息的段和可用的存储段是连续存放的,怎么保护这片记录信息的段呢 》?

3 楼

malloc返回的指针之前就是保留区,这里存放着一些特殊信息:)

4 楼

我同意1楼朋友的解释。

malloc分配每块内存,都需要多用一点内存,这点内存用于存储块大小信息和对齐,不同版本的实现对齐也不同。

我写过几个版本的malloc/free,其中一个版本是这样的,在32位系统上,对于小块内存的分配,额外空间一般是8字节,也就是说即使你申请0字节,malloc也会用8字节,你申请1~8字节,malloc用16字节,对于大块内存的分配,通常以页面对齐,即4096的倍数,极端一点,如果你申请4097字节,malloc将会消耗掉8192字节。不要认为这非常浪费,为了让系统正常执行您的程序,这是必须的。

更多内存管理的信息,建议你上我的主页把《数据结构和算法基础》的第8章下载下来看看,希望您耐心点,否则可能看不太懂。

5 楼

多说一句,您为何不用高一点版本的编译器?
PS: www.cppblog.com/chipset

6 楼

高一点版本的编译器?您推荐哪个?
我感觉VC高版本的太庞大了

7 楼

这只不过是对分配的内存空间对齐而已。这不能算是内存的占用。

如果不对内存的分配进行这样的对齐,只能产生更大的浪费。

按照winodws来说,C运行库有一个默认的堆,所有的malloc都在这个堆上分配内存。
这个分配的内存堆是在进程建立以后,main函数开始执行以前,以Windows的C运行时启动代码的形式进行申请。

所谓的内存占用主要在于这个堆的大小,另外我们知道一个进程里还有各个段,比如数据段,代码段。


只能说,写出楼主的那些代码的作者把事情想的简单了。

完整的理解这个问题在Windows下的情形需要很多知识,主要是PE文件格式,Windows的内核对象,Windows中的内存堆的概念,线程上下文,进程上下文,X86处理器的保护模式,内存分页,段的概念等等。



无论如何,写出这样的代码娱乐一下也可以当做一种消遣了。。。

我来回复

您尚未登录,请登录后再回复。点此登录或注册