【问题标题】:how to find the maximum limit of Memory Allocation in c如何在c中找到内存分配的最大限制
【发布时间】:2017-07-03 21:16:20
【问题描述】:

我想确定我可以在我的计算机中分配的最大内存限制是多少。这是我为此任务编写的代码:

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

int main() {
    int j;
    int *primes;
    int i ;

    int limit = 2147483647;

    primes = malloc(sizeof(int) * limit);
    for (i = 0; i < limit; i++)
    {
        primes[i] = 1;
    }
    return 0;
}

如何确定可以分配多少内存而无需点击和试用?我在这个例子中分配了最大的 int 大小。但是程序崩溃了。 在这个例子中实际分配了多少内存?

【问题讨论】:

  • 首先,你的代码是错误的。您没有检查malloc() 是否成功,因此您没有实现您想要的。 “在这个例子中实际分配了多少内存?” --> 可能没有。
  • @MichaelWalz 是的,但这涉及“打击和审判”,不是吗?
  • 另外,您需要注意一些现代操作系统 overcommit,也就是说,它们(似乎)分配了比可用内存更多的内存,作为物理内存和交换空间.例如,我的 Ubuntu 系统有 32 GB 物理内存和只有 4 GB 交换空间,因此它不可能有超过 36 GB 的“实际虚拟”内存,但 malloc 愉快地分配了 131071 GB(是的,131 gigabytes),然后程序在填满 10 GB 时被系统杀死。
  • XY 问题。你为什么想知道?即使有一个函数可以获取当前可用内存(物理的?虚拟的?),在该函数返回到多处理系统上的代码之前,它可能已经出错了。
  • 旁注:1 不是质数。

标签: c memory-management malloc dynamic-memory-allocation


【解决方案1】:

您可以分配的最大内存量受多个因素控制,并且会随时间而变化。

其中包括: 1. 硬件限制 2. 操作系统限制 三、系统参数 4. 进程配额 5.页面文件空间

此外,malloc 是一种非常糟糕的分配大块内存的方法。

您的程序崩溃了,因为 malloc 返回 null 并且您在没有检查的情况下使用该返回值。

【讨论】:

  • 我已经检查了 malloc 已经返回 NULL 你是对的,所以请告诉我如果 malloc 非常差,我应该怎么做来分配大块
【解决方案2】:

循环执行的迭代次数太多,您设计的这是程序崩溃或循环死无穷的主要原因。

由于有一些关键说明,您期望知道的答案非常复杂---->>

1. 这取决于程序运行的平台,例如 Windows、Linux 或 Mac。 我认为内存量不受限制 除了物理内存之外的任何东西。

事实-> 虽然物理内存可能会被虚拟内存扩展,但并非所有平台都具有“虚拟内存”的功能。 C没有虚拟内存的概念。 Malloc 分配连续的内存(意味着并排或一起在 ram 中)。
因此,这取决于平台处理请求的方式。这取决于 C 实现。

2. 标准类型“size_t”(由 声明)可表示的最大数(以字节为单位)。这个值可以而且确实在不同的实现中有所不同。请注意,此值不一定与主机(即最终用户)平台的可用内存一样大。

问题。对此有什么限制吗?我应该去哪里 这种信息?

回答。 Malloc 的参数是 size_t 并且该类型的范围是 [0,SIZE_MAX],因此您可以请求的最大值是 SIZE_MAX,其值因实施而异并且是中定义。

注意:- SIZE_MAX 字节的请求是否成功取决于本组范围之外的因素。

【讨论】:

  • Mension nt Bhaijan ;) 如果 @AzamAli 真的很有帮助,那么如果你真的愿意,你可以投票赞成 ans,这样它可能对像你一样的其他人有帮助。 :)
【解决方案3】:

你的代码是错误的,原因有很多,比如

  • 假设最大尺寸(对于平台/环境)最不可能是真实的,更不便携。
  • 假设 malloc() 提供部分分配(直到可用内存),这又是错误的。

    引用C11 标准,第 7.22.3.4 章,(强调我的

    malloc 函数返回空指针或指向已分配空间的指针。

    所以,它要么完全成功(分配的请求内存的确切数量)或完全失败(返回空指针),没有像部分这样的权衡可用内存或任何您可能假设的成功。

  • 您没有检查 malloc() 是否成功,从而导致可能的空指针取消引用。

  • 您无法实际检查分配是否成功/失败

我相信,您需要getrlimit() 和家人来实现您的目的。特定的兴趣点将是 RLIMIT_DATA 作为 resource 值。

也就是说,

1. "我在这个例子中分配了最大的 int 大小"

无论如何,这似乎与malloc() 和家人的限制无关。

2. “但是程序崩溃了”

这很可能是undefined behavior 的结果。在您的代码中,您直接取消引用返回的指针,而没有成功检查malloc()malloc() 很可能失败并返回了 NULL,取消引用会导致 UB。

【讨论】:

  • 也使用int limit = 2147483647;。这可以替换为来自limits.hINT_MAX
  • @RoadRunner 但这与手头的这个问题无关,对吧?这些是不同的限制,在我看来,这个特定的值在这里没有意义。
  • 我同意,我想这只是 OP 可以考虑的。只是想我会提到它,因为您在 OP 的代码中指出问题。
  • @RoadRunner 澄清一下,我并不是要反驳你,我只是澄清一下,即使在进行了更改之后,代码也没有多大意义。附上我的答案。 :)
  • @RoadRunner 但是当我设置的限制小于 1500000 时,此代码有效。
【解决方案4】:

malloc() 允许失败,在这种情况下它返回一个 NULL 指针不分配任何内存。它始终是all-or-nothing分配。它要么成功并分配请求大小的完整内存块,要么失败,返回 NULL 指针而不分配单个字节。

至于知道有多少内存可用 - 这实际上取决于环境:您在什么操作系统中运行它,是 16 位、32 位还是 64 位内存架构?

例如,如果您在 Windows 10 上运行,则可以使用GlobalMemoryStatusEx() 工具(有关详细信息,请参阅MSDN:GlobalMemoryStatusEx())。

Linux, OTOH 提供了一种简洁的sysconf() 方式来检索类似信息。详情请参考this page

即使您的操作系统是 64 位,也不一定意味着您的 应用程序 可以访问超过特定限制。例如,Windows 7 64 位仅允许您在应用程序代码中寻址多达 8GB 的​​内存,即使完整的虚拟内存空间为 16TB。

【讨论】:

  • 这样一个函数返回的任何值在操作系统上有什么用处,在函数返回之前,另一个进程可以分配这么多的内存?通常人们无法选择需要多少内存。如果那是用于缓冲区:将其留给操作系统和 libc。无论如何,他们大多数时候都知道得更好。 (对于非常特殊的软件可能会有所不同,但无论如何初学者都不会写)
  • GlobalMemoryStatusEx() 返回(在ullAvailVirtual 中)用户进程 可用的内存量。其他用户模式应用程序不会超过该内存,因为它们是孤立的并且不会占用彼此的内存空间。在上面的答案中查看我对 Windos 7 的评论(接近尾声)
  • 这意味着它不能保证在在所有情况下都是可分配的。除非 Windows 是第一个真正的透视操作系统。没有那个我的评论仍然适用。 (顺便说一句,user 进程限制的前缀“全局”非常容易误导。)这与内存空间无关(如果两个进程具有相同的内存空间,这确实很奇怪 - 不包括共享内存)。但也许这是一些 DOS 扩展程序认为“实时内存双倍”在 80 年代末/90 年代初广泛传播。但那些只是蛇油。
  • 没有什么是可以保证的(除了死亡和税收),这就是为什么程序将大部分代码用于错误处理
  • 您错过了重点:如果该函数的值与实际使用无关,为什么还要查询它?毕竟,OP 很可能存在 XY 问题。
猜你喜欢
  • 1970-01-01
  • 2023-03-20
  • 2017-11-14
  • 2012-06-27
  • 2017-11-02
  • 2023-03-20
  • 2010-11-18
  • 2021-12-23
  • 1970-01-01
相关资源
最近更新 更多