《"Expert C programming"》一书中的内存分配练习



这个练习让我看看在接下来的程序中,如果要分配的内存块小于1MB会发生什么:

#include <stdio.h>
#include <stdlib.h>
main()
{
    int MB=0;
    while(malloc(1<<20))
        ++MB;
    printf("Allocated %d MB totaln",MB);
}

我的笔记本电脑上的结果是

已分配3056 MB

然后我像这样修改程序:

#include <stdio.h>
#include <stdlib.h>
main()
{
    int MB=0;
    while(malloc(1<<19))
        ++MB;
    printf("Allocated %d MB totaln",MB/2+MB%2);
}

结果是

已分配3045mb

我自己修改的程序正确吗?为什么结果小于3056MB?

  1. 是的,你的程序是好的。(尽管总是四舍五入兆字节数是有点不标准的。)

  2. 当你调用free时,你不告诉它你释放的块有多大。这意味着内存管理系统必须知道每个块有多大。这意味着它必须把这些信息存储在某个地方。由于它不能将信息存储在内存块内,它必须将其存储在块外,这通常意味着实际分配的内存比请求的稍微多一些。例如,它实际上可以分配一个比请求的块大一个size_t的块,在开始时存储块大小,然后告诉你块在大小之后开始

大多数malloc实现将在页面边界上进行大的分配(通常一个页面是4K)。这样做的一种方法是为每次分配浪费整个页面,仅为单个size_t值使用页面。这看起来很糟糕,但是如果您要求的是半兆字节,那么一个页面的分配大小不到1%,浪费总内存的1%也没有那么糟糕。

假设malloc这样做了。当您分配1MB块时,您设法分配了其中的3056个。如果每个分配比请求大一个4k页面,那么隐藏的分配将是3056*4k,或者略小于12兆字节。(实际上它略小于12mebibytes,但是当我说mebi的时候我会一直说mega。)所以可用的总内存应该是3068 MB。

当您将其更改为分配½MB块时,您将设法分配至少3045*2 - 1个块(假设MB的数量是四舍五入)。这是6089个额外的页面,大约是23.8 MB,再加上3044.5 MB的分配,总共大约是3068.3 MB。

这些都不能证明malloc是这样工作的,但它至少显示了一种可能的机制。

1。当你运行这个程序时,你不会每次都得到相同的结果。因为您从堆中分配1MB内存块,直到内存可用,并且特定时间的可用内存可能会变化。

2。你的代码没有问题。

3。您不会在分配内存之后释放内存,所以通常操作系统会在程序存在之后释放分配的内存。这取决于操作系统,嵌入式操作系统(RTOS)通常不会为你释放内存。

最新更新