我试图创建一个三维数组 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++;}
它工作正常(对于像S [40] [40] [40]这样的小尺寸......当尺寸很大时,例如:
m=1500;
int S[m][m][m];
memset(S, 0, sizeof(S[1][1][1])*m * m * m);
....
....
我的程序停止工作可能是因为内存使用或其他类似的东西,我不确定...不知道吗?
感谢。
答案 0 :(得分:2)
你必须动态分配这么大的数组。这是一种方法:
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 );
修改强>
考虑到这一点,它需要大约12.5 Gb来存储1500 3 4字节整数;你无法在32位系统上实现这一点(它最多只能支持4 Gb的虚拟地址空间)。您需要一个64位系统,但即便如此,您仍然无法在单个连续的块中分配那么多空间。
另一种方法是进行零碎的分配,如下:
bool success = true;
size_t i, j;
m = 1500;
int ***S = calloc( m, sizeof *S );
if ( !S )
// bail out here
// Breadth-first allocation strategy, we allocate all a[i] first,
// make sure they all succeeded, and *then* allocate each a[i][j].
for ( i = 0; success && i < m; i++ )
{
S[i] = calloc( m, sizeof *S[i] );
success = (S[i] != NULL );
}
// If allocating any S[i] failed, free all S[0] through S[i-1], *then*
// free S. Freeing S alone won't free each S[i].
if ( !success )
{
while ( i-- )
{
free( S[i] );
}
free( S );
// bail out here
}
// for each S[i], allocate S[i][j].
for ( size_t i = 0; success && i < m; i++ )
{
for ( size_t j = 0; success && j < m; j++ )
{
S[i][j] = calloc( m, sizeof *S[i][j] );
success = (S[i][j] != NULL );
}
}
// Same deal - if any S[i][j] allocation failed, free all S[i][0] through
// S[i][j-1], *then* free all S[0] through S[i], *then* free S.
if ( !success )
{
do
{
while ( j-- )
free( S[i][j] );
free( S[i] );
} while ( i-- );
free( S );
// bail out here
}
此时,您已分配足够的内存来存储m
x m
x m
元素;
像任何3D数组S[i][j][k]
一样索引。与3D阵列不同,个人
行在内存中不相邻 - 你最终看起来像这样:
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]
+---+ +---+ +---+
S
指向int **
的1500个元素序列 1 ;每个S[i]
指向一个1500个元素的int *
序列;每个S[i][j]
指向一个1500个元素的int
序列。
优点 - 没有单个内存块(5到10 Kb,具体取决于指针大小)。
缺点 - 行在内存中不相邻,因此您不能仅仅行走&#34;行走&#34;使用单个指针通过整个数组,您无法在单个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 );
同样,这假设您的系统可以支持超过16 GB的虚拟地址空间(即64位)。如果没有,你就无法在这么大的时期建造结构。
<小时/>
S
,S[i]
和S[i][j]
都不是数组。这些项中的每一项都是指针,而不是数组。
答案 1 :(得分:0)
您的代码存在多个问题:
您的数组是可变长度数组。这意味着该阵列最有可能在堆栈上分配,其大小有限(在Linux上默认为8192 KiB,如果是使用过的系统)。假设sizeof(int) == 4
,
此空间已用尽m = 128
。对于m >= 128
,您将获得分段错误,因为访问的内存区域超出了堆栈的边界,因此将访问(最可能)未分配的堆内存的地址。
对于m = 128
,阵列将消耗8 MiB,即使通常的32位操作系统应该能够处理总共4GiB的内存,也不会 。但是内存消耗增长了3的幂。对于m = 1500
,将使用总共~12.6 GiB(准确地说是1.35e10字节)。这超出了stack
的大小,如果在堆上分配内存,甚至可能会导致问题。上面提到的32位系统作为一个例子将会扼杀这一点(PAE被忽略的特殊情况)。
如果要为m
支持超过127的值,则必须在堆上分配内存。这将推动限制以匹配所提供系统可以处理的内存大小。所有上述计算均为粗略估计,不考虑特殊情况,不应采用字面意义。他们应该做的是给人一种可以处理的上限的印象。