如何确保以下功能没有过度分配?

时间:2019-05-29 21:36:32

标签: c function pointers memory malloc

我正在尝试创建一个函数,该函数获取列和行的数目(宽度和高度),构建2D矩阵,然后将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, 尽管Matrix [0] [30]-存在并且可以访问。

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

2 个答案:

答案 0 :(得分:1)

您的分配没有问题。在C语言中,如果您走出了界限,并且很幸运,您会收到一个分段错误信号,并且该程序终止(如果您尚未为此信号安装特定的信号处理程序),但是如果您到达某个有效内存,则可以访问记忆力和破坏某些东西的风险。

就像其他人在评论中说的那样,C不会捕获编码错误,但是如果您使用标志-Wall -pedantic -g进行编译,则编译器将在某些内容关闭时生成一些警告,有时甚至会提示您如何解决错误。还了解如何使用valgrind

答案 1 :(得分:1)

您的分配方案没有错,但是有许多改进尚待完成。如果您的调试器报告可以到达30个元素的行,则您查看信息的方式有问题。

首先,无需强制返回malloc,这是不必要的。参见:Do I cast the result of 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变量和函数名,而推荐使用所有小写字母< / em>保留大写名称供宏和常量使用。这是样式问题-完全由您决定)

也请注意::使用perror代替printf进行错误报告。当函数将errno设置为失败时,perror应该使用。此外,它已经在stderr上提供了输出。如果处理未设置errno的故障,则使用fprintf(如果需要转换)或{{1 }},然后在fputs而不是stderr上报告错误

仔细检查一下,如果还有其他问题,请告诉我。