【问题标题】:crash on trying to reallocate a pointer using pointer to this pointer尝试使用指向此指针的指针重新分配指针时崩溃
【发布时间】:2015-02-03 18:25:36
【问题描述】:

我有一个指向指针(“路径”)的指针,我想重新分配每个指针(每个“路径”)。但我遇到了崩溃。一般来说,我试图找到一个数字的所有可能的幂,一个可以计算一定数量的操作(例如,对于两个操作,我们可以获得三和四的幂(一个操作用于数字的平方,然后另一个操作用于幂三或四个))。我想出了如何在纸上做到这一点,现在我正在尝试在代码中实现它。这是我的尝试:

#include <stdio.h>
#include <stdlib.h>

void print_path(const int *path, int path_length);

int main(void)
{
    fputs("Enter number of operations? ", stdout);
    int operations;
    scanf("%i", &operations);
    int **paths, *path, npaths, npath;
    npaths = npath = 2;
    path = (int*)malloc(npath * sizeof(int));
    paths = (int**)malloc(npaths * sizeof(path));
    int i;
    for (i = 0; i < npaths; ++i)    // paths initialization
    {
        int j;
        for (j = 0; j < npath; ++j)
            paths[i][j] = j+1;
    }
    for (i = 0; i < npaths; ++i)    // prints the paths, all of them are displayed correctly
        print_path(paths[i], npath);

    for (i = 1; i < operations; ++i)
    {
        int j;
        for (j = 0; j < npaths; ++j) // here I am trying to do it
        {
            puts("trying to reallocate");
            int *ptemp = (int*)realloc(paths[j], (npath + 1) * sizeof(int));
            puts("reallocated");    // tried to write paths[j] = (int*)realloc...
            paths[j] = ptemp;   // then tried to make it with temp pointer
        }
        puts("memory reallocated");
        ++npath;
        npaths *= npath;    // not sure about the end of the loop
        paths = (int**)realloc(paths, npaths * sizeof(path));
        for (j = 0; j < npaths; ++j)
            paths[j][npath-1] = paths[j][npath-2] + paths[j][j];
        for (j = 0; j < npaths; ++j)
            print_path(paths[j], npath);

        puts("\n");
    }
    int c;
    puts("Enter e to continue");
    while ((c = getchar()) != 'e');
    return 0;
}

void print_path(const int *p, int pl)
{
    int i;
    for (i = 0; i < pl; ++i)
        printf(" A^%i -> ", p[i]);
    puts(" over");
}

【问题讨论】:

  • 您使用临时指针来防止覆盖以前的paths[j],但您仍然永远不会检查realloc 是否返回NULL
  • 现在我检查了它,但它没有帮助,程序在重新分配行崩溃并且没有提前进行返回值检查,也许我在重新分配时做错了
  • 另外,从malloc/realloc 中删除演员表,它不会修复您的程序,但它会使其更具可读性。
  • 您正在使用pathpaths 并为它们所代表的指针分配内存,但从不为要写入的数据分配内存(空间)。 (即类似for(i=0;i&lt;n;i++)( path[i] = malloc(...);}
  • 我在 // 路径初始化之前做了类似的事情,我猜它可以工作,因为后来我通过调用 print_path(paths[i], npath); 打印所有路径;

标签: c pointers crash allocation pointer-to-pointer


【解决方案1】:

我不确定问题出在对realloc() 的调用上,而是您正在尝试写入尚未为其创建空间的位置...
尽管您为指针创建内存,但不会为实际存储位置创建空间(分配内存)。

这是一个为int 的二维数组分配内存的函数示例

int ** Create2D(int **arr, int cols, int rows)
{   
    int space = cols*rows; 
    int    y;

    arr   = calloc(space, sizeof(int));
    for(y=0;y<cols;y++)
    {
        arr[y] = calloc(rows, sizeof(int)); 
    }
    return arr;
}  

void free2DInt(int **arr, int cols)
{
    int i;
    for(i=0;i<cols; i++)
        if(arr[i]) free(arr[i]);
    free(arr);  
}

使用示例

#include <ansi_c.h>
int main(void)
{
    int **array=0, i, j;
    array = Create2D(array, 5, 4);
    for(i=0;i<5;i++)
        for(j=0;j<4;j++)
            array[i][j]=i*j; //example values for illustration
    free2DInt(array, 5);

    return 0;

}

这里的另一点是,很少有一个好主意[m][c][re]alloc() 的返回函数

编辑

此插图显示了我对您的代码的运行,就像您展示的那样:

发生错误时,i==0 & j==0paths[0][0] 处的指针未初始化。

编辑 2
要重新分配 int 的二维数组,您可以使用类似:

int ** Realloc2D(int **arr, int cols, int rows)
{   
    int space = cols*rows; 
    int    y;

    arr   = realloc(arr, space*sizeof(int));
    for(y=0;y<cols;y++)
    {
        arr[y] = calloc(rows, sizeof(int)); 
    }
    return arr;
}    

这是一个演示它如何工作的测试函数:

#include <stdio.h>
#include <stdlib.h>

int ** Create2D(int **arr, int cols, int rows);
void free2DInt(int **arr, int cols);
int ** Realloc2D(int **arr, int cols, int rows);

int main(void)
{
    int **paths = {0};
    int i, j;

    int col = 5;
    int row = 8;

    paths = Create2D(paths, col, row);
    for(i=0;i<5;i++)
    {
        for(j=0;j<8;j++)
        {
            paths[i][j]=i*j;    
        }
    }
    j=0;
    for(i=0;i<5;i++)
    {

        for(j=0;j<8;j++)
        {
            printf("%d ", paths[i][j]); 
        }
        printf("\n");
    }
    //reallocation:
    col = 20;
    row = 25;

    paths = Realloc2D(paths, col, row);
    for(i=0;i<20;i++)
    {
        for(j=0;j<25;j++)
        {
            paths[i][j]=i*j;    
        }
    }
    j=0;
    for(i=0;i<20;i++)
    {

        for(j=0;j<25;j++)
        {
            printf("%d ", paths[i][j]); 
        }
        printf("\n");
    }

    free2DInt(paths, col);

    getchar();
    return 0;
}

【讨论】:

  • 感谢您的代码,但我确实创建了空间,并且使用 realloc 我试图扩大空间。这个空间的结构大致是:first_row(cell, cell), second_row(cell, cell)。并且单元格中的值已成功打印。我想要完成的是将我的数组扩展为:first_row(cell,cell,cell),second_row(cell,cell,cell)。也许我错了,没有创建空间,但是如何打印这个空间的整数?
  • @sasha199568 - 请参阅答案中的编辑。您可能正在使用分配函数来创建内存,但仅用于指针,而不用于数据。
  • 感谢您的帮助。我决定在不重新分配内存的情况下实现它(注意到在知道操作数量之后知道确切的内存量)。在我的下一次尝试中,我尝试使用 malloc 并理解我使用 malloc 的方式是错误的,我真的必须为数组的每个元素分配内存。但我仍然不明白这些值是如何在我发布的代码中打印出来的......
  • @sasha199568 - 关于但我仍然不明白我发布的代码中的值是如何打印的,有时您可以访问您不拥有的内存区域,有时你不能。我怀疑如果您能够打印数组的元素,而无需首先拥有它们(通过内存分配或声明)然后您调用 undefined behavior,这是要避免的事情.在这种情况下,C 标准没有为一段代码访问它不明确拥有的内存定义(指定)任何规则。有时有效,有时无效。
【解决方案2】:

realloc() 不会失败。失败的原因是在循环for (j = 0; j &lt; npaths; ++j) 中写入这些数组之前,您没有为paths[previous_npaths]paths[new_npaths-1] 之间的新指针分配内存。

【讨论】:

  • @ryyker 击败我发现了缺陷 ;-)
  • 下次我会好好评论我的节目。我相信我写入创建的位置,因为即使我在路径 [previous_npaths] 和路径 [new_npaths-1] 之间创建了新数组(但我在失败循环之后这样做),在失败的循环中我开始重新分配内存第一个数组,确实存在(打印出来)。并且程序将字符串“试图分配”,但它没有“重新分配”,所以它在写入第一个数组时失败(它包含整数 1 和 2,它们被打印)
  • 说你“相信你写到创建的位置”并不是这样。为了强化我的观点(和@ryyker 的观点),我在 second realloc() 之后添加了您的程序缺乏的提示,以确定它是否有效。就在那时我注意到for (j = 0; j &lt; npaths; ++j) paths[j][npath-1] = paths[j][npath-2] + paths[j][j]; 中的缺陷在j &gt;= old_npaths 时中断。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-16
  • 2014-08-23
  • 1970-01-01
  • 2010-10-27
  • 2011-05-23
相关资源
最近更新 更多