当“ char bigChar [1U << 31-1];”时,为什么要使用malloc();工作正常吗?

StackOverflow https://stackoverflow.com/questions/839291

  •  22-07-2019
  •  | 
  •  

与静态数组相比,使用 malloc(除了失败时返回 NULL 之外)有什么优点?仅当循环未注释时,以下程序才会耗尽我所有的内存并开始填充交换。它不会崩溃。

...

#include <stdio.h>

unsigned int bigint[ 1u << 29 - 1 ];
unsigned char bigchar[ 1u << 31 - 1 ];

int main (int argc, char **argv) {
  int i;
/*   for (i = 0; i < 1u << 29 - 1; i++) bigint[i] = i; */
/*   for (i = 0; i < 1u << 31 - 1; i++) bigchar[i] = i & 0xFF; */

  getchar();
  return 0;
}

...

经过一番尝试和错误后,我发现上面是我的 32 位 Intel 机器上 GCC 4.3 允许的最大静态数组。这是标准限制、编译器限制还是机器限制?显然我可以拥有任意数量的它们。它会出现段错误,但前提是我要求(并尝试使用)比 malloc 给我的更多的东西。

有没有办法确定静态数组是否已实际分配并且可以安全使用?

编辑:我感兴趣的是为什么使用 malloc 来管理堆而不是让虚拟内存系统来处理它。显然,我可以将数组的大小设置为我认为需要的大小的许多倍,并且虚拟内存系统只会将需要的内容保留在内存中。如果我从不写信给例如这些巨大数组的末尾(或开头),那么程序就不会使用物理内存。此外,如果我可以写入每个位置,那么除了增加堆中的指针或搜索同一进程中先前的分配之外,malloc 还会做什么?

编者注: 1 << 31 导致未定义的行为 如果 int 是 32 位,所以我将问题修改为 1u. 。该问题的目的是询问有关分配大型静态缓冲区的问题。

有帮助吗?

解决方案

好吧,实际上有两个原因:

  1. 由于可移植性,某些系统不会为您进行虚拟内存管理。

  2. 您将不可避免地需要将此数组分成更小的块,以便它有用,然后跟踪所有块,最后当您开始“释放”不再需要的数组块时,您将遇到的问题 内存碎片.

总而言之,您最终将实现大量内存管理功能(实际上几乎是重新实现 malloc),而没有可移植性的好处。

因此原因如下:

  • 通过内存管理封装和标准化实现代码可移植性。

  • 通过代码重用的方式提高个人生产力。

其他提示

使用malloc,你可以扩展和收缩的数组:它变成动态的,所以您可以准确地分配给你需要的东西。

这被称为自定义的内存管理,我想。 你可以这样做,但你必须管理的存储自己该块。 你会风在这个块编写自己的malloc()回环。

关于:

  

在一些试验和错误,我发现了   以上是最大的静态数组   让我的32位英特尔机器上   与GCC 4.3。这是一个标准   限,编译器的限制,或机器   限制?

一上限将依赖于4GB(32位)的虚拟地址空间是如何用户空间与内核空间之间分配。对于Linux,我相信最常见的分区方案对用户空间地址的3 GB范围和1米GB范围内核空间地址。该分区是在内核编译时配置,2GB / 2GB和1GB / 3GB分裂也在使用。当可执行文件被加载,虚拟地址空间必须为每个物体分配不管实际内存是否被分配给备份。

您可能能够分配该巨大阵列中的一个范围内,而不是其他。例如,如果你的阵列是一个结构的成员,要通过周围的结构。一些环境对结构尺寸的32K限制。

正如前面提到的,你也可以调整你的记忆正是你需要的使用。它在性能关键上下文重要不被换出到虚拟内存如果能够避免它。

有没有办法比外出的范围其他自由堆栈分配。所以,当你实际使用的全球配置和VM具有ALLOC你真正的努力内存,它被分配,并会呆在那里,直到你的程序运行了。这意味着,任何过程将只生长在它的虚拟内存使用(函数具有局部堆栈分配和那些将被“释放”)。

您不能“养”栈内存一旦超出功能范围,它总是被释放。所以,你必须知道你会多少内存在编译时使用。

然后归结为多少INT富[1 << 29]的这个可以有。由于第一个占用整个存储器(在32位)和将(让谎言:0x000000处)所述第二将解决为0xffffffff或thereaobout。然后第三个会解决什么?一些32位指针不能表达。 (记住,堆栈保留在编译时部分地解决,部分运行时,通过偏移量,多远时ALLOC这个或那个变量堆栈偏移被推动)。

因此,答案是相当多,一旦你有一个整型富[1 << 29]你不能有与其他地方堆栈变量函数的任何合理的深度了。

您真的应该避免这样做,除非你知道自己在做什么。尽量只要求尽可能多的内存需要。即使它没有被使用或其他它可以搞砸过程中自身项目的方式获得。有两个原因。首先,在某些系统上,特别是32位的人可引起地址空间,在极少数情况下过早地被耗尽。此外许多内核具有上保留/虚拟/不使用的内存某种每个进程的限制。如果你的程序在点在运行时询问内存,如果它要求被保留的内存超过这一限制的内核可以杀死进程。我见过要么崩溃或退出由于失败的malloc的,因为他们的记忆,而只有使用几MB GB的保留节目。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top