2

我想了解为什么多次调用动态分配的数据使用的内存比直接在代码上指定的内存或通过单次调用分配的内存要多malloc

例子

例如,我在 C 中编写了以下两个代码:

test1.c:int x 分配有malloc

int main (void)
{
    int *x;
    int i, n=1048576; //n=1024*1024;

    printf("size = %lu\n", n* sizeof(int));

    for(i=0; i<n; i++)
    {
        x = malloc(sizeof(int));
        *x=i;
    }
    printf("Look at top and then press something to finish.");fflush(stdout);
    getc(stdin);
    return 0;
}

为了简单起见,我没有在这里使用free 。当程序等待交互时,我查看另一个终端中的顶部函数,它向我显示:

PID  USER   PR  NI  VIRT   RES    SHR  S  %CPU %MEM  TIME+   COMMAND                                    
1384 root   20  0   41300  34076  1300 S  0.0  3.3   0:00.47 test1

test2.c:int x 不是动态分配的

int main (void)
{
    int x[1048576]; //x[1024*1024]
    int i, n=1048576;

    printf("size = %lu\n", n* sizeof(int));

    for(i=0; i<n; i++)
    {
        x[i]=i;
    }
    printf("Look at top and then press something to finish.");fflush(stdout);
    getc(stdin);
    return 0;
}

顶部向我展示:

PID  USER   PR  NI  VIRT    RES    SHR  S  %CPU %MEM  TIME+   COMMAND                                    
1352 root   20  0   12404   5500   1304 S  0.0  0.5   0:00.05 test2 

我还做了第三个代码,它的结果与我使用的 test2 相同:

x = malloc(n*sizeof(int));
for(i=0; i<n; i++)
    {
        x[i]=i;
    }

为什么进程的内存使用差异如此之大?那是因为 malloc 请求新的内存页面并且有内存被浪费了吗?还是malloc分配更多内存?

test1 使用3.3%的总内存,而 test2 使用0.5%

环境:

我正在 docker 内的 Centos 5 64 位上执行这些测试。

虚拟环境中的内存:

$ free -m
              total        used        free      shared  buff/cache   available
Mem:            995          98         845           3          51         808
Swap:          1162         194         967
4

2 回答 2

5

必须跟踪每个内存分配,以便free()释放空间以供重用。实际上,这意味着分配了最小内存大小;对于 32 位程序,它可以是 8 或 16 字节,对于 64 位程序,它可以是 16-32 字节(这取决于系统和使用的 C 库的版本)。

当你单独分配一百万个整数时,每个整数使用 8-32 个字节,所以你实际上使用了 8-32 MiB 的内存。当您在堆栈上的单个数组中分配一百万个整数时,您正在使用 4 MiB 的内存。

因此,您会看到流程大小存在显着差异。

当然,第一个程序几乎泄漏了所有内存,但这与您所问的问题相切。

于 2016-07-21T01:04:53.560 回答
2

每次用户请求一些内存时,系统都需要做一些整理工作。当仅使用指针调用 free 就足以让系统取消分配其内存时,应该记住这一点。

因此,在您的第一个示例中,您请求内存n时间,而在第二个示例中只请求一次。您打算使用的内存是相同的,但系统必须“记住”的信息却不同。

于 2016-07-21T01:03:16.937 回答