C 中的 malloc 可以有多大?
我在 C 中有一个 malloc,它是 26901^2*sizeof(double)
这让我思考这里的最大值是多少?
另外,定义宏来访问这个二维数组时会遇到任何问题吗?
#define DN(i,j) ((int)i * ny + (int)j)
因为这似乎对我不起作用——或者至少我不确定它是否有效。我不知道如何在宏上进行 TotalView 潜水来告诉我 A[DN(indx,jndx)] 实际在看什么。
I have a malloc in C that is 26901^2*sizeof(double)
This got me thinking what the largest value can be here?
Also, would I have any problems defining a macro to access this 2D array?
#define DN(i,j) ((int)i * ny + (int)j)
Because this seems to not be working for me - or I am at least unsure it is. I can't figure out how to make totalview dive on a macro to tell me what A[DN(indx,jndx)] is actually looking at.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
观察
假设一个典型的分配器,例如 glibc 使用的分配器,有一些观察:
malloc
调用mmap
获取页面)。实验
这是一个简单程序,用于分配最大的可能的块(使用
gcclargest_malloc_size.c -Wall -O2
编译:在我的
Linux stanley 2.6.32-上运行上述程序(
机器获得此结果:./a.out
) 24-generic-pae #39-Ubuntu SMP Wed Jul 28 07:39:26 UTC 2010 i686 GNU/Linux这是一个恰好 2800MiB 的分配 从
/proc/[number]/maps
:结论
看来堆已经被在程序数据和代码之间的区域以及共享库映射之间进行了扩展,这些映射紧贴用户/内核内存空间边界(在此系统上显然为 3G/1G)
此结果表明使用 malloc 的最大可分配空间大致等于:
注释
关于 glibc 和 Linux 实现,以下手册片段非常有趣:
malloc
mmap
后记
该测试是在 x86 内核上完成的。我预计 x86_64 内核会得到类似的结果,尽管返回的内存区域要大得多。其他操作系统在映射的位置以及大型 malloc 的处理方面可能会有所不同,因此结果可能会有很大不同。
Observations
Assuming a typical allocator, such as the one glibc uses, there are some observations:
malloc
.malloc
calling through tommap
to acquire pages).Experiment
Here's a simple program to allocate the largest possible block (compile with
gcc largest_malloc_size.c -Wall -O2
:Running the above program (
./a.out
) on myLinux stanley 2.6.32-24-generic-pae #39-Ubuntu SMP Wed Jul 28 07:39:26 UTC 2010 i686 GNU/Linux
machine obtains this result:This is an allocation of exactly 2800MiB. Observing the relevant mapping from
/proc/[number]/maps
:Conclusion
It appears the heap has been expanded in the area between the program data and code, and the shared library mappings, which sit snug against the user/kernel memory space boundary (obviously 3G/1G on this system).
This result suggests that the maximum allocatable space using malloc is roughly equal to:
Notes
With respect to glibc and Linux implementations, the following manual snippets are of great interest:
malloc
mmap
Afterword
This test was done on a x86 kernel. I'd expect similar results from a x86_64 kernel, albeit with vastly larger memory regions returned. Other operating systems may vary in their placement of mappings, and the handling of large
malloc
s, so results could be quite considerably different.这取决于您的 malloc 实现!
根据维基百科,“自 v2.3 版本以来,GNU C 库 (glibc) 使用修改后的 ptmalloc2,它本身基于 dlmalloc v2.7.0。” dlmalloc 指的是 Doug Lea 的 malloc 实现。在此实现中需要注意的重要一点是,大型 malloc 是通过操作系统的内存映射文件功能完成的,因此这些块实际上可以非常大,而不会出现查找连续块的许多问题。
That depends on your malloc implementation!
According to Wikipedia, "Since the v2.3 release, the GNU C library (glibc) uses a modified ptmalloc2, which itself is based on dlmalloc v2.7.0." dlmalloc refers to Doug Lea's malloc implementation. The important thing to note in this implementation is that large mallocs are accomplished through the operating system's memory mapped file functionality, so these blocks can be quite large indeed without many problems of finding a contiguous block.
malloc 问题已得到解答(取决于操作系统,您没有指定),因此关于定义:
不太安全,因为有人可能会执行
DN(a+b,c)
,它会扩展为这可能不是你想要的。因此,请在其中添加很多括号:
要查看
DN(indx,jndx)
指向什么,只需printf("%d\n",DN(indx,jndx));< /代码>
The malloc question is answered (depends on OS, which you don't specify), so about that define:
is not quite safe, for someone might do
DN(a+b,c)
which expands towhich is probably not what you wanted. So put a lot of parentheses in there:
to see what
DN(indx,jndx)
points to, justprintf("%d\n",DN(indx,jndx));
malloc 调用中的大小参数的类型为 size_t,该类型因实现而异。请参阅此问题了解更多的。
The size parameter in a call to malloc is of type size_t, which varies by implementation. See this question for more.
26'901^2 = 723'663'801。如果你的 double 是 8 个字节,那么它就小于 8GB。我认为分配这么多内存完全没有问题,而且我的应用程序通常会分配更多内存(在 64 位系统上)。 (我见过的最大内存消耗是 420GB(在具有 640GB RAM 的 Solaris 10 numa 系统上),最大连续块约为 24GB。)
最大值很难识别,因为它依赖于平台:与 32 位系统类似,它取决于用户-空间/内核空间分割。就目前情况而言,我认为首先会达到实际物理 RAM 的限制 - 在达到 libc 可以分配的限制之前。 (内核并不关心,它只是经常扩展虚拟内存,甚至不考虑是否有足够的 RAM 来固定它。)
26'901^2 = 723'663'801. If your double is 8 bytes, then it is less than 8GB. I see totally no problem allocating that much of memory and my apps routinely allocate (on 64 bit systems) much more. (Biggest memory consumption I have ever seen was 420GB (on Solaris 10 numa system with 640GB RAM) with largest continuous block of ~24GB.)
Largest value is hard to identify since it is platform dependent: similar to the 32bit systems it depends on user-space / kernel-space split. As things stand at the moment, I think one would first come to the limit of the actual physical RAM - before reaching the limit of what libc can allocate. (And kernel doesn't care, it just expands virtual memory often without even considering whether there is sufficient RAM to pin it to.)
您可以要求。您可以成功请求的最大数量显然取决于操作系统和单台计算机的配置。
malloc()
获取的最大内存块是最大的size_t
值 - 这是来自SIZE_MAX
代码>你的宏不安全。它使用
int
变量执行索引计算,该变量的范围只需达到 32767。任何高于此值的值都可能导致有符号溢出,从而导致未定义的行为。您可能最好以size_t
的形式进行计算,因为该类型必须能够保存任何有效的数组索引:(尽管请注意,如果您为
i
提供负值或j
,你会得到一个远远超出范围的索引)。The largest memory block you can ask
malloc()
for is the largestsize_t
value - this isSIZE_MAX
from<limits.h>
. The largest amount you can sucessfully request is obviously dependent on the operating system and the configuration of the individual machine.Your macro is not safe. It performs the index calculation with an
int
variable, which is only required to have a range up to 32767. Any value higher than this can cause signed overflow, which results in undefined behaviour. You are probably best off doing the calculation as asize_t
, since that type must be able to hold any valid array index:(Although note that if you supply negative values for
i
orj
, you'll get an index far out of bounds).