如何malloc块大小的UINT_MAX?

时间:2017-09-28 10:43:23

标签: c arrays malloc

我想创建一个具有UINT_MAX个索引的char arr[UINT_MAX]; // Compiler claims array size cannot be negative个数组。由于某些原因,这非常困难。我尝试过以下方法:

  • char* const arr = calloc(UINT_MAX, sizeof(char)); // Runs but seg fault when accessed
  • char* const arr = malloc(sizeof(char) * UINT_MAX); // arr is NULL
  • malloc/calloc

我不明白发生了什么。这是我的HEAP尺寸太低了吗?如果是这样,我该如何增加它? malloc可以不处理那种性质的块吗?我在calloc#We want to plot the mean for the whole region so we need a mean of all the lats and lons CCCma_mean = CCCma.collapsed(['latitude', 'longitude'], iris.analysis.MEAN, weights=CCCma_grid_areas) CRU_mean = CRU.collapsed(['latitude', 'longitude'], iris.analysis.MEAN, weights=CRU_grid_areas) UDel_mean = UDel.collapsed(['latitude', 'longitude'], iris.analysis.MEAN, weights=UDel_grid_areas) #PART 4: PLOT LINE GRAPH #limit x axis plt.xlim((1990,2008)) #assign the line colours qplt.plot(CCCma_mean.coord('year'), CCCma_mean, label='CanRCM4_ERAINT', lw=1.5, color='blue') qplt.plot(CRU_mean.coord('year'), CRU_mean, label='Observed_CRU', lw=2, color='black') qplt.plot(UDel_mean.coord('year'), UDel_mean, label='Observed_UDel', lw=2, color='black', linestyle='--') #create a legend and set its location to under the graph plt.legend(loc="upper center", bbox_to_anchor=(0.5,-0.05), fancybox=True, shadow=True, ncol=2) #create a title plt.title('Mean Near Surface Temperature for Malawi 1989-2008', fontsize=11) #add grid lines plt.grid() #save the image of the graph and include full legend #plt.savefig('ERAINT_Temperature_LineGraph_Annual', bbox_inches='tight') #show the graph in the console iplt.show() API页面中找不到任何有用的内容。

这个问题适用于C和C ++。

Windows 7 64位,16GB RAM,CMake 3.6.1,GCC 7.11.1,并在CLion 64位上编译。

3 个答案:

答案 0 :(得分:5)

首先,我要指出的是,可以使用errno来检查API调用失败的原因。

现在,让我们检查你的尝试:

堆叠分配 - char arr[UINT_MAX]

您正尝试在堆栈上分配4294967295字节,这是不可行的,因为操作系统会将堆栈大小限制为更小的大小。您可以尝试使用此manual中指定的API来操作它。

<强>的malloc

在大多数情况下,堆分配会因单一原因而失败:操作系统无法分配足够大的连续内存。

并不是说你的系统没有4GB的可用内存,但完全有可能没有一大块连续的内存适合你的请求。所以,就像malloc MSDN page指出的那样:

  

malloc返回指向已分配空间的void指针,如果没有足够的可用内存,则返回NULL

<强>释放calloc

malloccalloc使用相同的底层机制,因此如果一个失败,您应该期望第二个失败。请参阅calloc remarks

MSDN page部分

关于Linux平台上malloc的有趣事实

根据评论的要求,我将在Linux上指出有关malloc实施的一些有趣事实,因为它有很大不同!

首先,Linux明确指出它使用乐观的内存管理算法:

  

默认情况下,Linux遵循乐观的内存分配策略。这意味着当malloc()返回非NULL时,无法保证内存确实可用。如果事实证明系统内存不足,那么一个或多个进程将被OOM杀手杀死

这意味着内存并非实际拥有并专用于被叫方,而是操作系统希望在他需要时可以为他提供内存,如果它不是&#39 ; t,它恢复了一些讨厌的手段。

编辑:正如@Basile Starynkevitch正确指出的那样,这种机制依赖于内存过量使用开关,默认情况下已启用,  但是can be disabled

答案 1 :(得分:2)

这是特定于操作系统的。但是,不检查malloccalloc的失败导致undefined behavior(例如您的calloc的段错误)并且总是错误(并且是基本的)错误你应该避免这样做)。请记住,malloccalloc可能会失败,并且在您请求或已经使用大量内存时更有可能失败(因为virtual memory是有限的资源)。请注意,sizeof(char)始终为1。

以下计划

 // file hatefiend.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <limits.h>

 int main(int argc, char**argv) {
   size_t sz = (argc>1)?(size_t)(atol(argv[1])):UINT_MAX;
   char *ad = malloc(sz);
   if (!ad) {perror("malloc"); exit(EXIT_FAILURE); };
   for (unsigned long ix=0; ix<(unsigned long)sz; ix += 1024)
     ad[ix] = (char)(' ' + (ix & 0x3f));
   printf ("ad=%p sz=%zd\n", ad, sz);
   /// the code below is optional and Linux specific, 
   /// remove it or adapt it for Windows
   char cmd[80];
   snprintf(cmd, sizeof(cmd), "pmap %d", (int)getpid());
   printf ("command: %s\n", cmd);
   fflush(NULL);
   int bad = system(cmd);
   if (bad) return  EXIT_FAILURE;
   return 0;
 }   

在具有16 GB RAM的Linux / Debian / x86-64笔记本电脑系统上运行良好(并且gcc -Wall -O hatefiend.c -o hatefiend移除ad后不会对其进行优化,因为它在printf中使用给予:

% ./hatefiend
ad=0x7fc3d5c09010 sz=4294967295
command: pmap 31644
31644:   ./hatefiend
000056355b8e3000      4K r-x-- hatefiend
000056355bae3000      4K r---- hatefiend
000056355bae4000      4K rw--- hatefiend
000056355c3de000    132K rw---   [ anon ]
00007fc3d5c09000 4194308K rw---   [ anon ]
00007fc4d5c0a000   1612K r-x-- libc-2.24.so
00007fc4d5d9d000   2048K ----- libc-2.24.so
00007fc4d5f9d000     16K r---- libc-2.24.so
00007fc4d5fa1000      8K rw--- libc-2.24.so
00007fc4d5fa3000     16K rw---   [ anon ]
00007fc4d5fa7000    140K r-x-- ld-2.24.so
00007fc4d6190000      8K rw---   [ anon ]
00007fc4d61c7000     12K rw---   [ anon ]
00007fc4d61ca000      4K r---- ld-2.24.so
00007fc4d61cb000      4K rw--- ld-2.24.so
00007fc4d61cc000      4K rw---   [ anon ]
00007ffe8f561000    132K rw---   [ stack ]
00007ffe8f5b7000     12K r----   [ anon ]
00007ffe8f5ba000      8K r-x--   [ anon ]
 total          4198476K

pmap(1)的输出可以看出,确实已经分配了内存。

您可以轻松地为您的Windows系统调整:删除<unistd.h>并更改snprintf以构建显示virtual address space的命令,即替换{某些特定于Windows的utility {1}};或者只删除命令的所有构建,即pmap及其用法......

所以帮自己一个忙:安装和使用Linux(可以看作是一种挑衅或一种有用的提示)。 Windows 可能 cmdmalloc失败。或者努力理解为什么发生了这种情况,并且可能在系统中配置以使巨大的calloc成功。如何做到这一点是一个系统管理员问题,超出Stack Overflow的范围(但你可以问 SuperUser)。小心memory overcommitment(我通常禁用它)。

  

我的HEAP尺寸是否太低?如果是这样,我该如何增加它?

您可能希望增加虚拟内存或虚拟地址空间限制(因为heap内存是malloc给出的内存。如何做到这一点是一个系统管理员问题(应该在SuperUser上询问),你需要提供更多细节才能获得帮助。

在评论中你提到你的malloc是一个32位整数(这让我很惊讶很多; 你是在64位模式编译吗? on我的Linux / x86-64机器是64位,如某些size_tuint64_t)。然后我相信你想要的东西在你的系统中是不可能的(因为unsigned long实现需要一些额外的空间 - 例如一些额外的单词用于簿记 - 并且可能计算一些内部malloc的开销。 ..)

请记住,this malloc(不是非常有用,但非常快)遵循C标准的字母。

但是我相信你有一些XY problem,你可以实现你的目标(没有说明)。这就是为什么激励问题对Stack Overflow很重要。也许将size_t声明为static variable可能会有所帮助:arr ....但请阅读this的缺点。

答案 2 :(得分:0)

不确定为什么你需要那么多char数组,但无论如何

char arr[UINT_MAX];

这对于堆栈大小来说太大了。没有编译器分配这么多堆栈大小。您可以在使用标记-stack进行编译时增加堆栈大小,但它仍然仅限于您的系统配置。

你可以通过调用命令ulimit -s来检查你的限制,并在尝试之前将其设置为无限ulimit -s unlimited。但是它仍然可能失败。

malloc返回NULL,因为它无法分配您要求的内存和calloc的内存。

增加虚拟内存或物理内存或两者以获取此内存。即使内存可用,它也可能会碎片到一定程度,系统无法满足您的请求。