我有一个奇怪的错误,我猜这个错误(像往常一样)在内存管理方面。这是我的代码:
#define LX 4
#define LY 4
int n = LX * LY;
void matrixInit( double *h );
int main(void)
{
int dim;
dim = (int) pow( 2.0, (double) n );
int k;
double *h;
h = (double *)malloc( dim * dim * sizeof(double) );
for(k = 0; k < dim * dim; k++)
{
h[k] = 0.0;
}
printf("dimension is: %d\n", dim);
matrixInit( h );
free( h );
return 0;
}
void matrixInit( double *h)
{
h[15379] = 0.0;
}
我有一个double
数组2^16
2^16
。我可以在main函数中为它赋值,没有问题。现在我创建了一个函数matrixInit
来更改数组中的值。访问元素0-15379
工作正常,但对于之后的任何元素,我得到&#34;分段错误(核心转储)&#34;。
答案 0 :(得分:3)
你陷入了使用不合适类型的陷阱。通常,索引数组的正确类型是size_t
。此类型显式是对平台上允许的所有索引有效的类型。
对于典型的32位和64位平台,int
为32位宽。这允许最大。 2**31 - 1
(**
=权力)。对于2**16 * 2**16 == "**32
条目,这显然是不够的。有符号整数的任何溢出都是标准的未定义行为。搜索那个词,你不想要它!简单地说:一旦发生就会丢失 - 无需进一步研究。
说,让我们试试吧。
首先要确保您可以索引大型数组。这很可能只适用于64位平台。为确保使用
#include <stdint.h>
_Static_assert( (SIZE_MAX >= (uintmax_t)YOUR_MAX_DIM * YOUR_MAX_DIM), "Platform does not support arrays that large" )
如果您没有标准兼容(即C11)编译器,请使用#ifdef
。 uintmax_t
是您平台上最大的无符号整数类型。由于我们假设至少符合C99,因此至少为64位(unsigned long long
所需的最小宽度)。
然后你必须确保所有的计算都被处理为size_t
。所以:
#define LX ((size_t)4)
#define LY ((size_t)4)
这可以防止标准整数转换产生麻烦。
然后始终使用正确的类型:
size_t n = LX * LY;
int main(void)
{
size_t dim;
dim = (size_t)1 << n; // don't use floating point for exact results!
等等。要非常小心,不要从常量中删除原始int
。
另一个问题是:你想要一个2D数组,也就是矩阵。但是你分配一个数组并有一个指向第一个条目的指针。指针不是数组!
对于2D数组和指向第一个条目的指针,使用:
double (*h)[dim];
这是指向一维数组的指针。这个1D数组是第二维或2D数组,因此指针仍然指向一维数组的第一个条目;只是这个条目本身就是一个数组。请注意,我们必须指定&#34; inner&#34;的维度。阵列。
然后,在C中你不应该投射void *
,malloc
&amp;朋友:
h = malloc( dim * sizeof(*h) );
我还使用了一个简单的方法,只使用h
点的大小。请记住,这是一维数组。但这种模式是普遍的。
然后,检查可能遇到与程序执行相关的错误的函数的结果:
if ( h == NULL )
exit(1);
如果没有分配数组,这将优雅地终止程序 - 对于大小的数组也是如此。
循环必须在dim
之上的内外循环中分割。使用正确的类型:
for ( size_t k = 0 ; k < dim ; k++)
for ( size_t j = 0 ; ...
h[k][j] = 0.0;
介意使用正常的2D索引和索引变量的本地定义。
对于输出,您还需要size_t
参数的正确类型:
printf("dimension is: %zu\n", dim);
并且不要忘记释放已分配的内存块:
free(h);
最后必须更改功能签名:
void matrixInit(size_t dim, double h[dim][dim]);
这是有效的,因为array-argument总是转换为指向第一个条目的指针。请注意,对于第一个索引(h
此处不再是数组)也是如此。这与
void matrixInit(size_t dim, double (*h)[dim]);
(与h
中main
的声明进行比较!)。但阵列符号在尺寸上更清晰。
当然,调用必须通过dim
,但数组仍然以h
传递。
另请注意,我将数组的维度传递给函数。这是必要的,因为
将所有必需信息传递给适当的函数通常是一种好的方式。否则你必须使用一个全局变量,这是一个明确的禁止。