如何在C语言中声明一个非常大的三维数组?
我正在尝试创建一个三维数组S[][] 当尺寸较小时,例如:如何在C语言中声明一个非常大的三维数组?,c,multidimensional-array,initialization,out-of-memory,C,Multidimensional Array,Initialization,Out Of Memory,我正在尝试创建一个三维数组S[][] 当尺寸较小时,例如: m=40; int S[m][m][m]; memset(S, 0, sizeof(S[1][1][1])*m * m * m); //initialize all the array with 0// for (i=1 ; i<=m ; i++ ) { k=1; for (j=1 ; j<=n ; j++ ) { if(statement) { //if s
m=40;
int S[m][m][m];
memset(S, 0, sizeof(S[1][1][1])*m * m * m); //initialize all the array with 0//
for (i=1 ; i<=m ; i++ ) {
k=1;
for (j=1 ; j<=n ; j++ ) {
if(statement) { //if statment true i put in S array a value//
S[i][i][k]=j; k++;}
m=1500;
int S[m][m][m];
memset(S, 0, sizeof(S[1][1][1])*m * m * m);
....
....
我的程序可能停止工作,可能是因为内存使用,或者类似的,我不知道…知道吗
谢谢。您必须动态分配这么大的阵列。这里有一个方法:
m = 1500;
int (*S)[m][m] = calloc( m, sizeof *S );
if ( !S )
{
fprintf( stderr, “Fatal: unable to allocate array\n” );
exit( EXIT_FAILURE );
}
for ( i = 0; i < m; i++ )
{
k = 0;
for ( j = 0; j < m; j++ )
{
if ( expr )
{
S[i][i][k++] = j;
}
}
}
free( S );
S
指向int**
的1500个元素序列1;每个S[i]
都指向int*
的1500个元素序列;每个S[i][j]
都指向int
的1500个元素序列
优点-没有一块内存那么大(5到10KB,取决于指针大小)
缺点-行在内存中不是相邻的,因此不能用一个指针“遍历”整个数组,也不能在单个memcpy
或fwrite
调用中复制或序列化数组
如果出现故障,请小心回滚任何部分分配-仅释放S
不会释放为每个S[i]
或S[i][j]
分配的内存
完成后,需要按与分配相反的顺序取消分配:
// free in reverse order of allocation
for ( i = 0; i < m; i++ )
{
for ( j = 0; j < m; j++ )
free( S[i][j] );
free( S[i] );
}
free( S );
//按与分配相反的顺序释放
对于(i=0;i
同样,这假设您的系统可以支持16 GB以上的虚拟地址空间(即64位)。如果没有,你将无法建造这么大的建筑
S
、S[I]
、以及S[I][j]
都不是这样的数组。这些项中的每一项都是指针,而不是数组。
您的代码存在多个问题: 您的数组是可变长度数组。这意味着数组最有可能在堆栈上分配,而堆栈的大小是有限的(在linux上,默认值是8192kib,如果这是使用的系统)。假设
sizeof(int)==4
,
当m=128
时,此空间将耗尽。对于m>=128
您将得到一个分段错误,因为访问的内存区域超出堆栈的边界,因此(很可能)将访问未分配堆内存的地址
内存消耗
对于m=128
,阵列将消耗8个MiB,考虑到即使是普通的32位操作系统也应能够处理总共4GB的内存,该MiB并不是那么大。但是内存消耗以3的幂增长。对于m=1500
,总共将使用~12.6Gib(精确地说是1.35e10字节)。这远远超出了堆栈的大小,如果在堆上分配内存,甚至可能导致问题。上面提到的32位系统作为一个例子,将在此基础上阻塞(忽略PAE等特殊情况)
总结
如果您想为m
支持127以外的值,则必须在堆上分配内存。这将推动限制以匹配所提供系统可处理的内存大小。以上所有计算都是粗略估计,不考虑特殊情况,也不应按字面计算。他们应该这样做,以便对可以处理的上限有一个印象。m=1500;整数S[m][m][m]代码>对于堆栈来说太大。使用malloc
;ii=0;iint(*S)[m][m]=malloc(m*sizeof*S)代码>您也在索引数组的边界。C中的数组索引是从零开始的,所以在您的例子中是从0到m-1。您需要在执行任何其他操作之前修复该问题。memset(S,0,sizeof(S[1][1][1])*m*m*m)代码>->memset(S,0,sizeof S)代码>谢谢,但是当你的意思是如果(!S){//内存分配失败,在这里退出}然后使用S?在S数组中,使用for,我给出这样的值。。。S[1][1][1]=2,。。。[1][1][2]=8。。。如果一个状态为false,它将停止(例如,直到S[1][1][8]=x,然后继续到S[2][2][1]…到S[m][m][1]…我如何使用你说的这个方法?我不知道是否可能(从StackOverFlow系统)若要将代码作为评论发布在此处,以100%理解我的问题,@NakosKotsanis:代码是正确的,并回答了标题中的问题。如果您有不同的问题,请阅读并提出新问题。我确信代码是正确的,但我真的不明白如何使用@JohnBobe所说的代码…除了标题之外,我不知道如何使用它这是一个解释问题的描述。如果因为我不知道如何在我的案件中使用它,所以我向John询问更多细节的事实是被禁止的,那么为什么会有“描述字段”以及回答更多细节的可能性?…无论如何,你知道的更好;)@NakosKotsanis:在“if”语句的主体中,您将记录一个错误并返回(因此称为“bail out”);代码的其余部分仅在分配成功时执行。
int *** int ** int * int
+---+ +---+ +---+ +---+
S:| | ------> | | S[0] ------> | | S[0][0] --------> | | S[0][0][0]
+---+ +---+ +---+ +---+
| | S[1] | | S[0][1] | | S[0][0][1]
+---+ +---+ +---+
... ... ...
+---+ +---+ +---+
| | S[m-1] | | S[0][m-1] | | S[0][0][m-1]
+---+ +---+ +---+
// free in reverse order of allocation
for ( i = 0; i < m; i++ )
{
for ( j = 0; j < m; j++ )
free( S[i][j] );
free( S[i] );
}
free( S );