C语言 如何确保以下函数不会过度分配?



我正在尝试创建一个函数来获取列数和行数(宽度和高度),构建一个二维矩阵,然后将 Matrix[0][0] 的地址返回到原始调用方函数中的指针。

int **allocateMatrix(int width, int height) // function that allocate 
//memory for 2D matrix and check that memory allocation was successful
{
int **Matrix;
int row;
Matrix = (int**)malloc(sizeof(int*)*height); 
if (!Matrix)
{
printf("failed to allocate memory. this program is over.n");
exit(1);
}
for (row = 0; row < height; row++)    
{   Matrix[row] = (int*)malloc(sizeof(int)*width);     
if (!Matrix[row])
{ 
printf("failed to allocate memory. this program is over.n");
exit(1);
}
}
return Matrix;
}

在分配过程中,我通过调试器观察了整个事情,它似乎创建了一个比我预期的太大的矩阵,以及通常的意外行为。 如:高度=5,宽度=5, 虽然矩阵[0][30] - 存在且可访问。

此外,我不确定我返回的地址。

您的分配没有问题。在 C 语言中,如果你超出边界并且很幸运,你会得到一个分段错误信号并且程序终止(如果你没有为此信号安装特定的信号处理程序),但如果你落在某个有效的内存上,你可以访问该内存并冒着损坏某些东西的风险。

正如其他人在评论中所说,C 不会捕获编码错误,但如果您使用标志进行编译-Wall -pedantic -g编译器会在出现问题时生成一些警告,有时它甚至会给你一个关于如何修复错误的提示。另请了解如何使用valgrind

您的分配方案没有任何问题,但有许多改进可以做到的。如果您的调试器报告可以访问 30 个元素的行 - 则您查看信息的方式有问题。

首先,没有必要投malloc的回归,这是不必要的。请参阅:我是否投射了 malloc 的结果?

避免分配函数中的exit。调用方应该可以选择正常处理分配失败,而不是程序在此时退出。虽然exit有效,但它严重限制了您处理故障的选项。相反,在成功时返回有效的指针,否则NULL,并让调用方处理错误。如果分配失败,则由您free()所有以前的分配,然后再返回NULL

请考虑使用callocmatrix[row]分配存储。calloc将所有分配给零的字节设置为零,有效地初始化每行的每个元素,0以防止在返回后无意访问未初始化的元素时出现未定义的行为

将所有部分放在一起,您可以执行以下操作:

/* allocatematrix allocates storage for a width x height matrix of type int.
* all elements are initialized zero. on success returns a pointer to pointer
* to type, otherwise all allocations are freed and NULL is returned.
*/
int **allocatematrix (int width, int height)
{
int **matrix;
int row;    /* declare row in for loop declaration, unless c89 support needed */
matrix = malloc (height * sizeof *matrix);  /* allocate pointers */
if (!matrix) {                  /* validate */
perror ("malloc-matrix");   /* malloc failure set errno, use it */
return NULL;                /* evaluate return in caller */
}
for (row = 0; row < height; row++) {    /* for each pointer */
matrix[row] = calloc (width, sizeof *matrix[row]);  /* alloc rows */
if (!Matrix[row]) {         /* validate */
perror ("calloc-matrix[row]");  /* ditto for calloc */
while (row--)           /* loop over previous rows */
free (matrix[row]); /* free previously allocated rows */
free (matrix);          /* free pointers */
return NULL;            /* evaluate return in caller */
}
}
return matrix;  /* return initial pointer address */
}

(注意:虽然不是错误,但 C 通常避免使用camelCaseMixedCase变量和函数名称,而支持所有写,同时保留大写名称以用于宏和常量。这是一个风格问题 - 所以它完全取决于你)

(另请注意:使用perror而不是printf进行错误报告。当函数在失败时设置errno时,应使用perror。此外,它已经在stderr上提供了输出。如果在未设置errno的情况下处理故障,则使用fprintf(如果需要转换)或以其他方式fputs并在stderr而不是stdout上报告错误)

仔细查看,如果您有其他问题,请告诉我。

相关内容

  • 没有找到相关文章

最新更新