一个malloc在C中有多大?

Der*_*rek 26 c malloc macros totalview

我在C中有一个malloc,它是26901 ^ 2*sizeof(double)

这让我想到这里最大的价值是什么?

另外,定义宏来访问这个2D数组有什么问题吗?

 #define DN(i,j) ((int)i * ny + (int)j)
Run Code Online (Sandbox Code Playgroud)

因为这对我来说似乎不起作用 - 或者我至少不确定它是不是.我无法弄清楚如何在宏上进行全视图潜水,告诉我A [DN(indx,jndx)]实际上是在看什么.

Mat*_*ner 38

意见

假设一个典型的分配器,例如一个glibc使用的,有一些观察结果:

  1. 无论是否实际使用了内存,都必须在虚拟内存中连续保留该区域.
  2. 最大的自由连续区域取决于现有内存区域的内存使用情况以及这些区域的可用性malloc.
  3. 映射实践取决于体系结构和操作系统.此外,获取内存区域的底层系统调用受这些实践的影响(例如malloc调用mmap以获取页面).

实验

这是一个分配最大可能块的简单程序(编译时使用gcc largest_malloc_size.c -Wall -O2:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static void *malloc_wrap(size_t size)
{
    void *p = malloc(size);
    if (p) {
        printf("Allocated %zu bytes from %p to %p\n", size, p, p + size);
    }
    else {
        printf("Failed to allocated %zu bytes\n", size);
    }
    return p;
}

int main()
{
    size_t step = 0x1000000;
    size_t size = step;
    size_t best = 0;
    while (step > 0)
    {
        void *p = malloc_wrap(size);
        if (p) {
            free(p);
            best = size;
        }
        else {
            step /= 0x10;
        }
        size += step;
    }
    void *p = malloc_wrap(best);
    if (p) {
        pause();
        return 0;
    }
    else {
        return 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

./a.out在我的Linux stanley 2.6.32-24-generic-pae #39-Ubuntu SMP Wed Jul 28 07:39:26 UTC 2010 i686 GNU/Linux机器上运行上面的程序()得到这个结果:

<snip>
Allocated 2919235584 bytes from 0x9763008 to 0xb7763008
Allocated 2936012800 bytes from 0x8763008 to 0xb7763008
Failed to allocated 2952790016 bytes
Failed to allocated 2953838592 bytes
Failed to allocated 2953904128 bytes
Failed to allocated 2953908224 bytes
Allocated 2936012800 bytes from 0x85ff008 to 0xb75ff008
Run Code Online (Sandbox Code Playgroud)

这是一个完全2800MiB的分配.观察相关的映射/proc/[number]/maps:

<snip>
0804a000-0804b000 rw-p 00001000 08:07 3413394    /home/matt/anacrolix/public/stackoverflow/a.out
085ff000-b7600000 rw-p 00000000 00:00 0          [heap]
b7600000-b7621000 rw-p 00000000 00:00 0 
b7621000-b7700000 ---p 00000000 00:00 0 
b7764000-b7765000 rw-p 00000000 00:00 0 
b7765000-b78b8000 r-xp 00000000 08:08 916041     /lib/tls/i686/cmov/libc-2.11.1.so
<snip>
bfc07000-bfc1c000 rw-p 00000000 00:00 0          [stack]
Run Code Online (Sandbox Code Playgroud)

结论

看来堆已经扩展到程序数据和代码之间的区域,以及共享库映射,它紧贴用户/内核内存空间边界(显然是这个系统上的3G/1G).

这个结果表明使用malloc的最大可分配空间大致等于:

  1. 用户空间区域(示例中为3GB)
  2. 减少堆开始的偏移量(程序代码和数据)
  3. 减少为主线程堆栈保留的空间
  4. 减少共享库中所有映射所占用的空间
  5. 最后,底层系统可以在堆可用的区域内找到最大的连续区域(可能被其他映射分段)

笔记

关于glibc和Linux实现,以下手册片段引起了极大的兴趣:

malloc

   Normally, malloc() allocates memory from the heap, and adjusts the size
   of the heap as required, using sbrk(2).  When allocating blocks of mem?
   ory larger than MMAP_THRESHOLD bytes, the glibc malloc() implementation
   allocates the memory as a  private  anonymous  mapping  using  mmap(2).
   MMAP_THRESHOLD  is  128  kB  by  default,  but is adjustable using mal?
   lopt(3).
Run Code Online (Sandbox Code Playgroud)

mmap

   MAP_ANONYMOUS
          The mapping is not backed by any file; its contents are initial?
          ized to zero.
Run Code Online (Sandbox Code Playgroud)

后记

此测试在x86内核上完成.我期望x86_64内核有类似的结果,尽管返回的内存区域要大得多.其他操作系统的映射位置和大mallocs 的处理可能会有所不同,因此结果可能会有很大差异.


Hut*_*ut8 11

这取决于你的malloc实现!

根据维基百科的说法,"自从v2.3发布以来,GNU C库(glibc)使用了一个修改过的ptmalloc2,它本身就是基于dlmalloc v2.7.0." dlmalloc指的是Doug Lea的malloc实现.在这个实现中需要注意的重要事项是,通过操作系统的内存映射文件功能来完成大型malloc,因此这些块确实非常大,没有找到连续块的许多问题.


mvd*_*vds 7

malloc问题得到解答(取决于操作系统,你没有指定),所以关于那个定义:

#define DN(i,j) ((int)i * ny + (int)j)
Run Code Online (Sandbox Code Playgroud)

是不是很安全,因为有人可能会DN(a+b,c)扩展到

((int)a+b * ny + (int)c)
Run Code Online (Sandbox Code Playgroud)

这可能不是你想要的.所以在那里放了很多括号:

#define DN(i,j) ((int)(i) * ny + (int)(j))
Run Code Online (Sandbox Code Playgroud)

DN(indx,jndx)只是看看有什么意义printf("%d\n",DN(indx,jndx));