我已经写了一些运行在OS X 10.6上的C代码,它恰好很慢,所以我使用valgrind来检查内存泄漏等。
如果我将内存分配给一个2D数组,如下所示:
double** matrix = NULL;
allocate2D(matrix, 2, 2);
void allocate2D(double** matrix, int nrows, int ncols) {
matrix = (double**)malloc(nrows*sizeof(double*));
int i;
for(i=0;i<nrows;i++) {
matrix[i] = (double*)malloc(ncols*sizeof(double));
}
}然后检查矩阵的内存地址是否为0x0。
但是,如果我这样做了
double** matrix = allocate2D(2,2);
double** allocate2D(int nrows, int ncols) {
double** matrix = (double**)malloc(nrows*sizeof(double*));
int i;
for(i=0;i<nrows;i++) {
matrix[i] = (double*)malloc(ncols*sizeof(double));
}
return matrix;
}这工作得很好,即返回指向新创建的内存的指针。
当我还有一个free2D函数来释放内存的时候。它似乎不能正常释放。也就是说,指针仍然指向与调用free之前相同的地址,而不是0x0 (我认为这可能是默认的)。
void free2D(double** matrix, int nrows) {
int i;
for(i=0;i<nrows;i++) {
free(matrix[i]);
}
free(matrix);
}我的问题是:我误解了malloc/free是如何工作的吗?否则,有人能建议发生了什么事吗?
亚历克斯
发布于 2010-10-16 18:05:46
当您释放一个指针时,指针的值不会改变,如果您希望它为空,则必须将其显式设置为0。
发布于 2010-10-17 02:10:47
在第一个示例中,您只将malloc返回的指针存储在局部变量中。当函数返回时,它会丢失。
在C语言中,通常的做法是使用函数的返回值将指向已分配对象的指针传递回调用者。正如Armen所指出的,您还可以传递一个指针,指向函数应该存储其输出的位置:
void Allocate2D(double*** pMatrix...)
{
*pMatrix = malloc(...)
}但我认为大多数人一看到***就会尖叫。
您可能还认为指针数组不是矩阵的有效实现。单独分配每一行会导致内存碎片、malloc开销(因为每次分配都会涉及一些记账,更不用说必须存储的额外指针)和缓存未命中。而且每次访问矩阵的一个元素都会涉及两个指针引用,而不是只有一个,这可能会导致停顿。最后,您还有更多的工作要做,因为您必须检查每个malloc的故障,如果其中任何一个失败,则清理您已经做过的所有工作。
一种更好的方法是使用一维数组:
double *matrix;
matrix = malloc(nrows*ncols*sizeof *matrix);然后以matrix[i*ncols+j]的形式访问元素(i,j)。潜在的缺点是乘法(在古老的cpus上速度很慢,但在现代cpus上很快)和语法。
一种更好的方法是不寻求过度的概括性。SO上的大多数矩阵代码不是用于可能需要任意矩阵大小的高级数值数学,而是用于3d游戏,其中2x2、3x3和4x4是任何实际使用的唯一矩阵大小。如果是这样的话,试试下面这样的方法
double (*matrix)[4] = malloc(4*sizeof *matrix);然后,您可以将元素(i,j)作为matrix[i][j]访问,只需一个解引用和一个极快的乘以常量。如果您的matrix仅在本地作用域或结构中需要,则只需将其声明为:
double matrix[4][4];如果您不是非常熟悉C类型系统和上面的声明,那么最好还是将所有矩阵包装在struct中:
struct matrix4x4 {
double x[4][4];
};然后,声明、指针类型转换、分配等变得更加熟悉。唯一的缺点是你需要做像matrix.x[i][j]或matrix->x[i][j]这样的事情(取决于matrix是否是指向结构的指针的结构)而不是matrix[i][j]。
编辑:我确实想到了将矩阵实现为行指针数组的一个有用属性-它使行的排列成为一项微不足道的操作。如果您的算法需要执行大量的行置换,这可能是有益的。请注意,对于较小的矩阵,好处不会很多,而且列置换不能以这种方式进行优化。
发布于 2010-10-16 18:00:22
在C++中,您应该通过引用传递指针:)
Allocate2D(double**& matrix...)至于发生了什么,你有一个为空的指针,你将该指针的副本传递给分配内存的函数,并用新分配的内存的地址初始化指针的副本,但原始指针仍然为空。至于free,你不需要通过引用传递,因为只有指针的值是相关的。HTH
由于C中没有引用,所以可以通过指针传递,即
Allocate2D(double*** pMatrix...)
{
*pMatrix = malloc(...)
}然后像这样调用
Allocate2D(&matrix ...)https://stackoverflow.com/questions/3948412
复制相似问题